Микро-орм межоператорские транзакции в NestJS - PullRequest
1 голос
/ 25 февраля 2020

Я оцениваю Микро-Орм для будущего проекта. Есть несколько вопросов, на которые я либо не смог найти ответ в документах, либо не полностью их понял.

Позвольте мне описать минимальный сложный пример (Nest JS): у меня есть система обработки заказов с двумя объектами : Orders и Invoices, а также таблица счетчиков для последовательных номеров счетов (юридическое требование). Важно отметить, что метод создания OrderService вызывается не только контроллером, но и через систему crobjob / queue. Мои вопросы касаются варианта использования создания нового заказа:

class OrderService {
    async createNewOrder(orderDto) {
        const order = new Order();
        order.customer = orderDto.customer;
        order.items = orderDto.items;

        const invoice = await this.InvoiceService.createInvoice(orderDto.items);
        order.invoice = invoice;

        await order.persistAndFlush();

        return order
    }
}

class InvoiceService {
    async create(items): Invoice {
        const invoice = new Invoice();

        invoice.number = await this.InvoiceNumberService.getNextInSequence();

        // the next two lines are external apis, if they throw, the whole transaction should roll back
        const pdf = await this.PdfCreator.createPdf(invoice);
        const upload = await s3Api.uplpad(pdf);

        return invoice;
    }
}

class InvoiceNumberService {
  async getNextInSequence(): number {
      return await db.collection("counter").findOneAndUpdate({ type: "INVOICE" }, { $inc: { value: 1 } });
  }
}

Весь сценарий использования создания нового заказа со всеми последующими вызовами обслуживания должен происходить в одной транзакции Mikro-Orm. Таким образом, если что-то добавляет в OrderService.createNewOrder () или один из впоследствии вызванных методов, вся транзакция должна быть откатана.

  1. Микро-Орм не позволяет атомы c инкремент обновления показан в InvoiceNumberService. Я могу вернуться к родному драйверу mon go. Но как мне гарантировать, что вызов collection.findOneAndUpdate () использует ту же транзакцию, что и сущности, управляемые Mikro-Orm?

  2. Mikro-Orm нуждается в уникальном контексте запроса. В примерах для Nest JS этот уникальный контекст создается на уровне контроллера. В приведенном выше примере сервисные методы не обязательно вызываются контроллером. Поэтому мне нужен новый контекст для каждого вызова OrderService.createNewOrder (), который имеет время жизни, ограниченное вызовом функции, правильно? Как я могу достичь этого?

  3. Как я могу использовать один и тот же контекст запроса между службами? В приведенном выше примере для правильной работы InvoiceService и InvoiceNumberService необходим тот же контекст, что и OrderService для Mikro-Orm.

1 Ответ

0 голосов
/ 25 февраля 2020

Начну с плохой новости: транзакции mongodb еще не поддерживаются в MikroORM (хотя они могут приземлиться в течение нескольких недель, возможно, уже реализован Po C). Вы можете подписаться здесь на обновления: https://github.com/mikro-orm/mikro-orm/issues/34

Но позвольте мне ответить на остальное, как это будет применяться:

Вы можете использовать const collection = (em as EntityManager<MongoDriver>).getConnection().getCollection('counter');, чтобы получить коллекцию из внутреннего экземпляра подключения go. Вы также можете использовать orm.em.getTransactionContext() для получения текущего контекста транзакции (в настоящее время реализован только в sql драйверах, но в будущем это, вероятно, вернет объект session в mon go).

Также обратите внимание что в драйвере mon go неявные транзакции не будут включены по умолчанию (хотя это будет настраиваться), поэтому вам нужно будет использовать явное разграничение транзакций через em.transactional(...).

Помощник RequestContext работает автоматически. Вы просто регистрируете его как промежуточное ПО (выполняется автоматически в адаптере nest js orm), а затем ваш обработчик запросов (метод маршрута / конечной точки / контроллера) запускается в домене, который разделяет контекст. Благодаря этому все службы в DI могут совместно использовать единичные экземпляры репозиториев, но они автоматически выбирают правильный контекст из домена.

У вас в основном есть этот автоматический c контекст запроса, и затем вы можете создавать новые (вложенные) контексты вручную через em.transactional(...).

https://mikro-orm.io/docs/transactions/#approach -2 - явно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...