首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NestJS中的Mikro-orm服务间事务

NestJS中的Mikro-orm服务间事务
EN

Stack Overflow用户
提问于 2020-02-25 10:18:10
回答 1查看 1.1K关注 0票数 2

我正在为未来的项目评估Mikro-Orm。有几个问题我要么在文档中找不到答案,要么没有完全理解它们。

让我描述一个最小复杂示例(NestJS):我有一个包含两个实体的订单处理系统:OrdersInvoices,以及顺序发票号的计数器表(法律要求)。值得一提的是,OrderService create方法并不总是由控制器调用,而是通过crobjob/queue系统调用的。我的问题是关于创建新订单的用例:

代码语言:javascript
复制
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事务中。因此,如果有任何东西抛入OrderService.createNewOrder()或随后调用的方法之一,则应该回滚整个事务。

  1. Mikro-Orm不允许在InvoiceNumberService中显示原子更新增量。我可以回到本地的芒果司机那里。但是,如何确保对collection.findOneAndUpdate()的调用共享相同的事务,因为由collection.findOneAndUpdate管理的实体需要一个唯一的请求上下文。在NestJS的示例中,这个唯一的上下文是在控制器级别创建的。在上面的示例中,服务方法不一定由控制器调用。因此,对于每次调用OrderService.createNewOrder()都需要一个新的上下文,该调用的作用域为函数调用,对吗?如何做到这一点?
  2. 如何在服务之间共享相同的请求上下文?在上面的示例中,InvoiceService和InvoiceNumberService需要与OrderService相同的上下文才能正常工作.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-25 11:05:55

我将从坏消息开始,mongodb事务在MikroORM中还不受支持(虽然它们可能在几周内就会出现,但已经实现了PoC )。您可以在这里订阅更新:https://github.com/mikro-orm/mikro-orm/issues/34

但让我回答其余的问题,因为这样就适用了:

可以使用const collection = (em as EntityManager<MongoDriver>).getConnection().getCollection('counter');从内部mongo连接实例获取集合。您还可以使用orm.em.getTransactionContext()获取当前的trasaction上下文(目前只在sql驱动程序中实现,但在将来,这可能会返回mongo中的session对象)。

还请注意,在mongo驱动程序中,默认情况下不会启用隐式事务(虽然它是可配置的),因此您需要通过em.transactional(...)使用显式事务划分。

RequestContext助手自动工作。您只需将其注册为中间件(在nestjs orm适配器中自动完成),然后在共享上下文的域中运行请求处理程序(路由/端点/控制器方法)。由于这一点,DI中的所有服务都可以共享存储库的单例实例,但它们将自动从域中选择正确的上下文。

您基本上拥有这个自动请求上下文,然后您可以通过em.transactional(...)手动创建新的(嵌套的)上下文。

https://mikro-orm.io/docs/transactions/#approach-2-explicitly

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60392238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档