事务性消息:处理后新消息处理完成

编辑该页面

事务性消息:处理后新消息处理完成

一个消息处理程序可以调度新消息在处理其他相同或不同的总线(如果应用程序多个公共汽车)。在这个过程中发生的任何错误或异常可以产生意想不到的后果,如:

  • 如果使用DoctrineTransactionMiddleware和分派消息抛出一个异常,那么原始处理程序中的任何数据库事务将回滚。
  • 如果消息被分配到一个不同的总线,然后分派消息处理即使以后一些代码在当前处理器将抛出一个异常。

一个例子RegisterUser过程

让我们的应用程序的一个例子命令和一个事件公共汽车。应用程序发出一个命令命名RegisterUser到命令总线。命令处理的RegisterUserHandler这创建了一个用户对象,存储对象到数据库和分派UserRegistered事件总线消息。

有许多处理程序UserRegistered消息,一个处理程序可以发送欢迎邮件给新用户。我们使用的是DoctrineTransactionMiddleware包装在一个数据库事务中所有数据库查询。

问题1:如果抛出一个异常当发送欢迎邮件,然后用户将不会创建,因为DoctrineTransactionMiddleware将回滚事务原则,创建了用户。

问题2:如果抛出一个异常在保存用户到数据库,待发送邮件仍然是受欢迎的,因为它是异步处理的。

DispatchAfterCurrentBusMiddleware中间件

对于许多应用程序,所需的行为只有派出的处理消息处理程序一旦处理程序已全部完成。这可以通过使用DispatchAfterCurrentBusMiddleware和添加一个DispatchAfterCurrentBusStamp邮票消息信封:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39
/ / src /通讯/ CommandHandler / RegisterUserHandler.php名称空间应用程序\信使\CommandHandler;使用应用程序\实体\用户;使用应用程序\信使\命令\RegisterUser;使用应用程序\信使\事件\UserRegistered;使用学说\ORM\EntityManagerInterface;使用ob娱乐下载\组件\信使\信封;使用ob娱乐下载\组件\信使\MessageBusInterface;使用ob娱乐下载\组件\信使\邮票\DispatchAfterCurrentBusStamp;RegisterUserHandler{私人美元eventBus;私人美元新兴市场;公共函数__construct(MessageBusInterface美元eventBus,EntityManagerInterface美元新兴市场){美元- >eventBus =美元eventBus;美元- >em =美元新兴市场;}公共函数__invoke(RegisterUser美元命令){美元用户=用户(美元命令- >getUuid (),美元命令- >getName (),美元命令- >getEmail ());美元- >新兴市场- >persist (美元用户);/ / DispatchAfterCurrentBusStamp标志着事件消息处理/ /只有这个处理程序不抛出异常。美元事件=UserRegistered (美元命令- >getUuid ());美元- >eventBus- >调度((信封(美元事件))- >(DispatchAfterCurrentBusStamp ()));/ /……}}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27
/ / src /通讯/ EventSubscriber / WhenUserRegisteredThenSendWelcomeEmail.php名称空间应用程序\信使\EventSubscriber;使用应用程序\实体\用户;使用应用程序\信使\事件\UserRegistered;使用学说\ORM\EntityManagerInterface;使用ob娱乐下载\组件\梅勒\MailerInterface;使用ob娱乐下载\组件\Mime\RawMessage;WhenUserRegisteredThenSendWelcomeEmail{私人美元梅勒;私人美元新兴市场;公共函数__construct(MailerInterface美元梅勒,EntityManagerInterface美元新兴市场){美元- >梅勒=美元梅勒;美元- >em =美元新兴市场;}公共函数__invoke(UserRegistered美元事件){美元用户=美元- >新兴市场- >getRepository(用户::类)- >找到(美元事件- >getUuid ());美元- >梅勒- >发送(RawMessage (“欢迎”美元用户- >getFirstName ()));}}

这意味着UserRegistered消息才会处理RegisterUserHandler已完成和新吗用户被持久化到数据库中。如果RegisterUserHandler遇到一个异常,UserRegistered事件将不会被处理。如果抛出异常而发送欢迎邮件,教义事务不会被回滚。

请注意

如果WhenUserRegisteredThenSendWelcomeEmail抛出一个异常,该异常将包裹成一个DelayedMessageHandlingException。使用DelayedMessageHandlingException: getexception会给你所有的异常都扔在处理一条消息的吗DispatchAfterCurrentBusStamp

dispatch_after_current_bus中间件是默认启用。如果你手动配置您的中间件,一定要登记dispatch_after_current_bus之前doctrine_transaction在中间件链。此外,dispatch_after_current_bus中间件必须加载所有公共汽车的使用。

这项工作,包括代码示例,许可下Creative Commons冲锋队3.0许可证。
ob娱乐下载Symfony 6.0支持通过SensioLabs