A raven does not always arrive. The winds turn, dark towers scramble the routes… and some lands are simply out of reach.
The tavern now has a Voliere (aviary) service: it is the one that releases the birds. When the destination cannot be reached, it throws a VoliereIndisponible (aviary unavailable). Today, such an error would make the confirmation vanish. You need to retry, and then, if nothing works, set the message aside instead of losing it.
Your mission
- In the handler, hand the sending over to the aviary (
$this->voliere->envoyer(...), “send”). Let the exception bubble up: it is the failure signal. - In
messenger.yaml:- give the
asynctransport aretry_strategy: 2 retries, 1 second of waiting, doubled each time; - add an
echoues(failed) transport, and designate it as thefailure_transport; - during the tests, both transports live in memory, with a retry delay of zero: a test must not spend its time waiting.
- give the
What Messenger does on its own
When a handler throws an exception, the worker does not throw the message away: it puts it back in the queue with a delay, and tries again. After the last retry, the message goes to the failure transport. Nothing is lost, and the main queue is not blocked.
Each retry leaves a mark on the envelope, a stamp (RedeliveryStamp): you know how many times the message has already been tried.
In the console
messenger:consume async --limit=5 messenger:failed:show messenger:failed:retry
The first one handles the queue (try a reservation for Sauron in the “Requests” tab). The second lists the messages set aside, the third replays them, once the winds have calmed down.
Good habit
Retrying only makes sense for a temporary failure: a crowded aviary, a service that responds badly. An error that will happen again in exactly the same way (invalid data, for example) does not deserve a retry: better to set it aside right away.