@@ -9,9 +9,8 @@ a different bus (if the application has `multiple buses </messenger/multiple_bus
99Any errors or exceptions that occur during this process can have unintended consequences,
1010such as:
1111
12- - If using the ``DoctrineTransactionMiddleware `` and a dispatched message to the same bus
13- and an exception is thrown, then any database transactions in the original handler will
14- be rolled back.
12+ - If using the ``DoctrineTransactionMiddleware `` and a dispatched message throws an exception,
13+ then any database transactions in the original handler will be rolled back.
1514- If the message is dispatched to a different bus, then the dispatched message can still
1615 be handled even if the original handler encounters an exception.
1716
@@ -32,29 +31,28 @@ will not be created because the ``DoctrineTransactionMiddleware`` will rollback
3231Doctrine transaction, in which the user has been created.
3332
3433**Problem 2: ** If an exception is thrown when saving the user to the database, the welcome
35- email is still sent.
34+ email is still sent because it is handled asynchronously .
3635
37- ``HandleMessageInNewTransaction `` Middleware
38- --------------------------------------------
36+ ``DispatchAfterCurrentBusMiddleware `` Middleware
37+ ------------------------------------------------
3938
4039For many applications, the desired behavior is to have any messages dispatched by the handler
4140to `only ` be handled after the handler finishes. This can be by using the
42- ``HandleMessageInNewTransaction `` middleware and adding a ``Transaction `` stamp to
43- `the message Envelope </components/messenger#adding-metadata-to-messages-envelopes >`_.
44- This middleware enables us to add messages to a separate transaction that will only be
45- dispatched *after * the current message handler finishes.
41+ ``DispatchAfterCurrentBusMiddleware `` middleware and adding a ``DispatchAfterCurrentBusStamp ``
42+ stamp to `the message Envelope </components/messenger#adding-metadata-to-messages-envelopes >`_.
4643
4744Referencing the above example, this means that the ``UserSignedUp `` event would not be handled
4845until *after * the ``SignUpUserHandler `` had completed and the new ``User `` was persisted to the
4946database. If the ``SignUpUserHandler `` encounters an exception, the ``UserSignedUp `` event will
5047never be handled and if an exception is thrown while sending the welcome email, the Doctrine
5148transaction will not be rolled back.
5249
53- To enable this, you need to add the ``handle_message_in_new_transaction ``
54- middleware. Make sure it is registered before ``DoctrineTransactionMiddleware ``
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 ``
5553in the middleware chain.
5654
57- **Note: ** The ``handle_message_in_new_transaction `` middleware must be loaded for *all * of the
55+ **Note: ** The ``dispatch_after_current_bus `` middleware must be loaded for *all * of the
5856buses. For the example, the middleware must be loaded for both the command and event buses.
5957
6058.. configuration-block ::
@@ -70,13 +68,11 @@ buses. For the example, the middleware must be loaded for both the command and e
7068 messenger.bus.command :
7169 middleware :
7270 - validation
73- - handle_message_in_new_transaction
7471 - doctrine_transaction
7572 messenger.bus.event :
7673 default_middleware : allow_no_handlers
7774 middleware :
7875 - validation
79- - handle_message_in_new_transaction
8076 - doctrine_transaction
8177
8278
@@ -89,7 +85,7 @@ buses. For the example, the middleware must be loaded for both the command and e
8985 use App\Messenger\Event\UserSignedUp;
9086 use Doctrine\ORM\EntityManagerInterface;
9187 use Symfony\Component\Messenger\Envelope;
92- use Symfony\Component\Messenger\Stamp\Transaction ;
88+ use Symfony\Component\Messenger\Stamp\DispatchAfterCurrentBusStamp ;
9389 use Symfony\Component\Messenger\MessageBusInterface;
9490
9591 class SignUpUserHandler
@@ -108,13 +104,44 @@ buses. For the example, the middleware must be loaded for both the command and e
108104 $user = new User($command->getUuid(), $command->getName(), $command->getEmail());
109105 $this->em->persist($user);
110106
111- // The Transaction stamp marks the event message to be handled
107+ // The DispatchAfterCurrentBusStamp marks the event message to be handled
112108 // only if this handler does not throw an exception.
113109
114110 $event = new UserSignedUp($command->getUuid());
115111 $this->eventBus->dispatch(
116112 (new Envelope($event))
117- ->with(new Transaction ())
113+ ->with(new DispatchAfterCurrentBusStamp ())
118114 );
119115 }
120116 }
117+
118+ .. code-block :: php
119+
120+ namespace App\Messenger\EventSubscriber;
121+
122+ use App\Entity\User;
123+ use App\Messenger\Event\UserSignedUp;
124+ use Doctrine\ORM\EntityManagerInterface;
125+
126+ class WhenUserSignedUpThenSendWelcomeEmail
127+ {
128+ private $em;
129+ private $mailer;
130+
131+ public function __construct(MyMailer $mailer, EntityManagerInterface $em)
132+ {
133+ $this->mailer = $mailer;
134+ $this->em = $em;
135+ }
136+
137+ public function __invoke(UserSignedUp $eent)
138+ {
139+ $user = $this->em->getRepository(User::class)->find(new User($event->getUuid()));
140+
141+ $this->mailer->sendWelcomeEmail($user);
142+ }
143+ }
144+
145+ **Note: ** If ``WhenUserSignedUpThenSendWelcomeEmail `` throws an exception, that exception
146+ will be wrapped into a ``DelayedMessageHandlingException ``. Using ``DelayedMessageHandlingException::getExceptions ``
147+ will give you all exceptions that are thrown while handing a message with the ``DispatchAfterCurrentBusStamp ``.
0 commit comments