- Redis blocking dequeue no longer swallows
ConnectionError-- the error propagates to the worker, which logs it and applies exponential backoff. Previously a downed redis server caused workers to busy-loop silently. - Chord callbacks now fire when a member task is revoked, expired or cancelled by a pre-execute hook -- the skipped member contributes a
Noneplaceholder result. Previously the callback was silently lost. - Scheduler skips missed periodic checks after a stall (e.g. suspend/resume) instead of running them back-to-back, which enqueued duplicate periodic tasks for the current minute.
- Fix inverted timeout clamp in
wait_result()when usingnotify_resultwith redis < 6 (or an unknown server version): timeouts over one second were cut to 1s, and sub-second timeouts blocked indefinitely. put_if_empty()is now atomic for the memory and file storage backends, restoringlock_task()mutual exclusion on those backends.FileLockno longer unlinks an existing lock file at construction time, which broke mutual exclusion for any process already holding the lock.- Process-worker task timeouts use
signal.setitimer(), so float / sub-second timeouts work. Previously a timeout less than 1 second was silently ignored (alarm(0)cancels the timer) and fractional seconds were truncated. - Consumer signal handlers only set flags -- logging and greenlet cleanup now happen in the main loop, avoiding re-entrant I/O from signal context.
- A user-supplied task kwarg named
taskis no longer dropped during serialization. Context tasks (context=True) inject the task instance into a copy of the kwargs rather than mutating the task's data. MemoryStorage.dequeue()andadd_to_schedule()acquire the storage lock, like the other mutating methods.normalize_time()treatsdelay=0as "now" rather than ignoring it, so e.g.expires=0means "expires immediately" instead of "never expires".- Redis
enqueued_items(limit)returnedlimit + 1items from the producer end of the queue; it now returns the next-limititems to be dequeued, matching the other storage backends. - Redis-dependent tests are skipped when no local redis server is reachable, instead of failing at import time.
