Description
Symfony version(s) affected: 4.3.1
Description
When an exception is thrown during the handling of the first message, the queue is flushed and delayed messages which might already have been dispatched are "canceled".
On the other hand, if a delayed message handler throws an exception, it is simply collected without any queue cleanup being done.
Therefore, the DispatchAfterCurrentBusStamp
semantic is not the same whether we are in the first message handler or a delayed one. In the first case an exception "cancels" previously sent messages, in the second case it does not. I believe this is not intended since the messenger documentation clearly states (as an unintended consequences):
If the message is dispatched to a different bus, then the dispatched message will be handled even if some code later in the current handler throws an exception.
How to reproduce
Message A
dispatches (after current bus)Message B
and returns,Message B
dispatches (after current bus)Message C
but then throws an exception,Message C
is handled despite its dispatcher having thrown an exception
Possible Solution
Either:
- Implement two queues instead of one: delayed messages are stored in the second queue until the handler successfully completes, at that point the second queue is simply appended to the first one (the one being consumed by the while loop). That way we know which messages to throw away if an exception is thrown.
- Add some bookkeeping to save the length of the queue before executing a handler and discard any messages that have been added to it (by comparing length afterward) if the handler throws an exception. This solution is probably simpler since it does not affect the handling of the first message.
Additional context
n/a