1
1
.. index ::
2
2
single: Messenger; Record messages; Transaction messages
3
3
4
- Transactional Messages: Handle Events After CommandHandler is Done
4
+ Transactional Messages: Handle New Messages After Handling is Done
5
5
==================================================================
6
6
7
7
A message handler can ``dispatch `` new messages during execution, to either the same or
@@ -11,18 +11,18 @@ such as:
11
11
12
12
- If using the ``DoctrineTransactionMiddleware `` and a dispatched message throws an exception,
13
13
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.
16
16
17
17
An Example ``RegisterUser `` Process
18
18
-----------------------------------
19
19
20
20
Let's take the example of an application with both a *command * and an *event * bus. The application
21
21
dispatches a command named ``RegisterUser `` to the command bus. The command is handled by the
22
22
``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.
24
24
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
26
26
a welcome email to the new user. We are using the ``DoctrineTransactionMiddleware ``
27
27
to wrap all database queries in one database transaction.
28
28
@@ -33,88 +33,14 @@ Doctrine transaction, in which the user has been created.
33
33
**Problem 2: ** If an exception is thrown when saving the user to the database, the welcome
34
34
email is still sent because it is handled asynchronously.
35
35
36
- `` DispatchAfterCurrentBusMiddleware `` Middleware
37
- ------------------------------------------------
36
+ DispatchAfterCurrentBusMiddleware Middleware
37
+ --------------------------------------------
38
38
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
41
41
``DispatchAfterCurrentBusMiddleware `` middleware and adding a ``DispatchAfterCurrentBusStamp ``
42
42
stamp to `the message Envelope </components/messenger#adding-metadata-to-messages-envelopes >`_.
43
43
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
-
118
44
.. code-block :: php
119
45
120
46
namespace App\Messenger\CommandHandler;
@@ -185,8 +111,20 @@ buses. For the example, the middleware must be loaded for both the command and e
185
111
}
186
112
}
187
113
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
+
188
120
.. note ::
189
121
190
122
If ``WhenUserRegisteredThenSendWelcomeEmail `` throws an exception, that exception
191
123
will be wrapped into a ``DelayedMessageHandlingException ``. Using ``DelayedMessageHandlingException::getExceptions ``
192
124
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