Description
Symfony version(s) affected: 4.4 and up
Description
I've configured my failed transport with an infinite number of retries because I don't want to ever implicitly lose a message; I also want a cron to retry all failed messages once every couple of hours, to weed out temporary failures; that cron calls bin/console messenger:failed:retry --force
, which is stuck in a loop if the retry delay is low or zero, since it will retry all messages and then start over in this way:
- get message from failed transport
- gets message A
- retry and fails
- A is sent to failed transport
- get message from failed transport
- gets message A (with +1 retry count)
- goto 1
How to reproduce
- use this config
framework:
messenger:
failure_transport: failed
transports:
# ...
failed:
dsn: # use a transport of your choice
retry_strategy:
max_retries: 9999
delay: 0
- make at least one message that always fails wind up in the failed transport (maybe throwing in the handler)
- call
bin/console messenger:failed:retry --force
Possible Solution
I can probably workaround this issue by setting a fixed delay in the retry strategy, which is high enough to avoid getting messages caught in the loop, but determining the right amount of delay is hard because it's directly proportional to the amount of messages currently sitting in the failed transport.
I would prefer to have a way to reliably retry all failed messages in bulk, only once; I've tried to write a custom command to do that, but I don't see any way to use the Worker
in such fashion, and I would like to, to avoid loosing all the event dispatching logic bound to it.
The command says To retry all the messages, run messenger:consume failed
but it's not viable in a non-interactive situation, since it needs to be terminated manually.