Skip to content

Propagate queue dispatcher failures - #29

Open
jbaxendale-ut wants to merge 1 commit into
socketry:mainfrom
user-interviews:fix/supervise-dispatcher-failure
Open

jbaxendale-ut wants to merge 1 commit into
socketry:mainfrom
user-interviews:fix/supervise-dispatcher-failure

Conversation

@jbaxendale-ut

Copy link
Copy Markdown

I found this while digging into some delayed or stalled AI interview/speech turns in my app. We use Heroku Redis-backed AsyncJob queues, plus some separate app-specific concurrency controls. At first, those symptoms looked like queue contention but I also found a different failure mode: a queue server can return a lifecycle task whose blocking dequeue later dies. Ex: after Redis reconnection attempts run out.

The Active Job service starts that task but doesn’t wait on it, so its health loop can keep reporting ready even though the worker has stopped consuming jobs. From the outside, it looks like jobs are stuck until the worker restarts.

Disclaimer: I built this with Codex help, and this part of the stack is outside my usual area of expertise, so feedback appreciated! But I am running this adapter and related async-job-processor-redis fork changes in production successfully

This change:

  • waits for queue servers that return a lifecycle task
  • logs failures with the queue name and re-raises them so the existing service supervisor can restart the worker
  • stops constructed queues during teardown without creating a queue when startup failed
  • keeps synchronous/non-waitable processors, including Inline and Aggregate, working as before
  • adds coverage for failure propagation, teardown, queue attribution, non-waitable processors, and dispatcher stop delegation

Types of Changes

  • Bug fix.

Contribution

Validation

  • bundle exec sus — 39 tests, 143 assertions
  • bundle exec rubocop — no offenses

Wait for queue servers that expose a lifecycle task so a dispatcher failure exits the Active Job service and triggers its existing restart policy, instead of leaving the health loop ready without a dequeue worker.

Keep processors that return no waitable lifecycle handle alive, preserving Inline and Aggregate behavior.

Stop constructed queues during task teardown without building a queue when startup failed, and include the failed queue name in the emitted failure event.

Add coverage for task failure propagation, queue teardown, queue attribution, non-waitable processors, and dispatcher stop delegation.

Signed-off-by: Jeff Baxendale <jbaxendale@usertesting.com>
@jbaxendale-ut
jbaxendale-ut force-pushed the fix/supervise-dispatcher-failure branch from 5db311f to 5ea0768 Compare September 17, 2026 18:47

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant