11.. index ::
22 single: Messenger; Record messages; Transaction messages
33
4- Transactional Messages: Handle Events After CommandHandler is Done
4+ Transactional Messages: Handle New Messages After Handling is Done
55==================================================================
66
77A message handler can ``dispatch `` new messages during execution, to either the same or
@@ -11,18 +11,18 @@ such as:
1111
1212- If using the ``DoctrineTransactionMiddleware `` and a dispatched message throws an exception,
1313 then any database transactions in the original handler will be rolled back.
14- - If the message is dispatched to a different bus, then dispatched message will be
15- handled even if the current handler throws an exception.
14+ - If the message is dispatched to a different bus, then the dispatched message will
15+ be handled even if some code later in the current handler throws an exception.
1616
1717An Example ``RegisterUser `` Process
1818-----------------------------------
1919
2020Let's take the example of an application with both a *command * and an *event * bus. The application
2121dispatches a command named ``RegisterUser `` to the command bus. The command is handled by the
2222``RegisterUserHandler `` which creates a ``User `` object, stores that object to a database and
23- dispatches a ``UserRegistered `` event to the event bus.
23+ dispatches a ``UserRegistered `` message to the event bus.
2424
25- There are many subscribers to the ``UserRegistered `` event , one subscriber may send
25+ There are many handlers to the ``UserRegistered `` message , one handler may send
2626a welcome email to the new user. We are using the ``DoctrineTransactionMiddleware ``
2727to wrap all database queries in one database transaction.
2828
@@ -33,88 +33,14 @@ Doctrine transaction, in which the user has been created.
3333**Problem 2: ** If an exception is thrown when saving the user to the database, the welcome
3434email is still sent because it is handled asynchronously.
3535
36- `` DispatchAfterCurrentBusMiddleware `` Middleware
37- ------------------------------------------------
36+ DispatchAfterCurrentBusMiddleware Middleware
37+ --------------------------------------------
3838
39- For many applications, the desired behavior is to have any messages dispatched by the handler
40- to ` only ` be handled after the handler finishes . This can be by using the
39+ For many applications, the desired behavior is to * only * handle messages that are
40+ dispatched by a handler once that handler has fully finished . This can be by using the
4141``DispatchAfterCurrentBusMiddleware `` middleware and adding a ``DispatchAfterCurrentBusStamp ``
4242stamp to `the message Envelope </components/messenger#adding-metadata-to-messages-envelopes >`_.
4343
44- Referencing the above example, this means that the ``UserRegistered `` event would not be handled
45- until *after * the ``RegisterUserHandler `` had completed and the new ``User `` was persisted to the
46- database. If the ``RegisterUserHandler `` encounters an exception, the ``UserRegistered `` event will
47- never be handled and if an exception is thrown while sending the welcome email, the Doctrine
48- transaction will not be rolled back.
49-
50- The ``dispatch_after_current_bus `` middleware is enabled by default. It is configured as the
51- first middleware on all busses. When doing a highly custom or special configuration, then make
52- sure ``dispatch_after_current_bus `` is registered before ``doctrine_transaction ``
53- in the middleware chain.
54-
55- **Note: ** The ``dispatch_after_current_bus `` middleware must be loaded for *all * of the
56- buses. For the example, the middleware must be loaded for both the command and event bus.
57-
58- .. configuration-block ::
59-
60- .. code-block :: yaml
61-
62- # config/packages/messenger.yaml
63- framework :
64- messenger :
65- default_bus : messenger.bus.command
66-
67- buses :
68- messenger.bus.command :
69- middleware :
70- - validation
71- messenger.bus.event :
72- default_middleware : allow_no_handlers
73- middleware :
74- - validation
75-
76- .. code-block :: xml
77-
78- <!-- config/packages/messenger.xml -->
79- <?xml version =" 1.0" encoding =" UTF-8" ?>
80- <container xmlns =" http://symfony.com/schema/dic/services"
81- xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
82- xmlns : framework =" http://symfony.com/schema/dic/symfony"
83- xsi : schemaLocation =" http://symfony.com/schema/dic/services
84- https://symfony.com/schema/dic/services/services-1.0.xsd" >
85-
86- <framework : config >
87- <framework : messenger default_bus =" messenger.bus.command" >
88- <framework : bus name =" messenger.bus.command" >
89- <framework : middleware id =" validation" >
90- <framework : middleware id =" doctrine_transaction" >
91- </framework : bus >
92- <framework : bus name =" messenger.bus.command" default_middleware =" allow_no_handlers" >
93- <framework : middleware id =" validation" >
94- <framework : middleware id =" doctrine_transaction" >
95- </framework : bus >
96- </framework : messenger >
97- </framework : config >
98- </container >
99-
100- .. code-block :: php
101-
102- // config/packages/messenger.php
103- $container->loadFromExtension('framework', [
104- 'messenger' => [
105- 'default_bus' => 'messenger.bus.command',
106- 'buses' => [
107- 'messenger.bus.command' => [
108- 'middleware' => ['validation', 'doctrine_transaction'],
109- ],
110- 'messenger.bus.event' => [
111- 'default_middleware' => 'allow_no_handlers',
112- 'middleware' => ['validation', 'doctrine_transaction'],
113- ],
114- ],
115- ],
116- ]);
117-
11844.. code-block :: php
11945
12046 namespace App\Messenger\CommandHandler;
@@ -185,8 +111,20 @@ buses. For the example, the middleware must be loaded for both the command and e
185111 }
186112 }
187113
114+ This means that the ``UserRegistered `` message would not be handled
115+ until *after * the ``RegisterUserHandler `` had completed and the new ``User `` was persisted to the
116+ database. If the ``RegisterUserHandler `` encounters an exception, the ``UserRegistered `` event will
117+ never be handled. And if an exception is thrown while sending the welcome email, the Doctrine
118+ transaction will not be rolled back.
119+
188120.. note ::
189121
190122 If ``WhenUserRegisteredThenSendWelcomeEmail `` throws an exception, that exception
191123 will be wrapped into a ``DelayedMessageHandlingException ``. Using ``DelayedMessageHandlingException::getExceptions ``
192124 will give you all exceptions that are thrown while handing a message with the ``DispatchAfterCurrentBusStamp ``.
125+
126+ The ``dispatch_after_current_bus `` middleware is enabled by default. If you're
127+ configuring your middleware manually, be sure to register
128+ ``dispatch_after_current_bus `` before ``doctrine_transaction `` in the middleware
129+ chain. Also, the ``dispatch_after_current_bus `` middleware must be loaded for *all * of
130+ the buses being used.
0 commit comments