↓ Ir para o conteúdo principal

← todas as notas

📎 Webclip

Don’t Fear the Reaper: Detecting Failed Delayed Job Workers

The post proposes a way to retry Delayed Job tasks sooner when a worker crashes, is restarted, or is shut down by autoscaling. Instead of waiting for max_run_time to expire, it adds heartbeat tracking and a reaper that unlocks jobs tied to workers that have stopped reporting.

Reading notes
#

  • Delayed Job stores lock metadata in the delayed_jobs table, including locked_at and locked_by.
  • A job becomes eligible again when it is not locked by another worker or when the lock is older than max_run_time.
  • The author says max_run_time is too long in their setup because it must accommodate long-running bulk import and export jobs.
  • The solution has two parts: a plugin that writes heartbeat data for each worker and a reaper that unlocks jobs for workers without recent heartbeats.
  • The heartbeat design uses three pieces: WorkerModel, WorkerHeartbeat, and a Plugin that hooks into the worker lifecycle.
  • WorkerModel keeps each worker name and last heartbeat timestamp, and it includes scopes for dead workers and active names.
  • WorkerHeartbeat runs a background thread that updates the heartbeat on an interval and shuts down with a self-pipe trick.
  • The heartbeat thread is set to abort on exception, and on shutdown it removes the worker record and clears active database connections.
  • The plugin starts the heartbeat before worker execution and stops it after execution.
  • The reaper deletes dead worker records, finds jobs whose locked_by value is not among active workers, and clears locked_at, locked_by, and increments attempts.
  • In the author’s Heroku setup, a clockwork process runs the unlock routine on a schedule.
  • The article ends with configuration values for enabling heartbeats, setting heartbeat interval, setting timeout, and setting the dead-worker polling interval.