You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Worker enters restart loop when broker.listen() raises a transient exception #658
While investigating an issue with taskiq-redis's ListQueueBroker after upgrading to redis-py 8, I noticed that an exception raised by broker.listen() terminates the worker process, after which the process manager immediately schedules a replacement.
The original broker-specific issue is documented here:
In that particular case, redis-py 8 changed its default socket_timeout to 5 seconds while ListQueueBroker performs an indefinitely blocking BRPOP. When the queue remains empty, the Redis client raises redis.exceptions.TimeoutError.
The relevant sequence is roughly:
broker.listen()
-> BRPOP waits for a message
-> redis.exceptions.TimeoutError
-> exception propagates out of the receiver
-> worker process dies
-> process manager schedules reload
-> same thing happens again
Result:
worker-0 is dead. Scheduling reload.
worker-1 is dead. Scheduling reload.
This can result in a continuous worker restart loop while the underlying condition persists.
Question
Independently of how taskiq-redis should handle the Redis timeout itself, is it intentional for an exception from broker.listen() to terminate the worker process?
Some broker/listener errors can be transient, such as:
temporary network failures;
backend connection resets;
read timeouts;
short backend outages.
It seems potentially useful for Taskiq to distinguish between:
an unrecoverable broker failure that should terminate the worker; and
a transient receive/listen failure where the receiver could retry, possibly with backoff.
If recovery from transient listen() failures is deliberately considered the broker implementation's responsibility, it would be useful to document that explicitly as part of the broker contract.
I'd like to work on this, here is my plan, but I wanted to check the direction with a maintainer first.
Proposal: in the receiver's listen loop, catch exceptions raised by broker.listen() and retry with exponential backoff (for example starting at 1s and capped at 30s) instead of letting the worker process die. The error gets logged each time, and the backoff resets once a message is received. A configurable max retry count (or a worker CLI flag) would still let the worker exit on a persistent failure, so the process manager behaviour stays the same in that case.
If you'd rather keep this as the broker's responsibility, I can instead send a docs PR that states it clearly in the broker contract.
Which way would you prefer? I can test it with a fake broker whose listen() raises once, no Redis needed.
Activity
astroknot-sheep commentedon Oct 28, 2026
I'd like to work on this, here is my plan, but I wanted to check the direction with a maintainer first.
Proposal: in the receiver's listen loop, catch exceptions raised by
broker.listen()and retry with exponential backoff (for example starting at 1s and capped at 30s) instead of letting the worker process die. The error gets logged each time, and the backoff resets once a message is received. A configurable max retry count (or a worker CLI flag) would still let the worker exit on a persistent failure, so the process manager behaviour stays the same in that case.If you'd rather keep this as the broker's responsibility, I can instead send a docs PR that states it clearly in the broker contract.
Which way would you prefer? I can test it with a fake broker whose
listen()raises once, no Redis needed.