2,300 bullmq jobs stuck in active after a deploy, lockduration is default Worker Setup
Deployed at 14:02. By 14:05 active was 2,300 and climbing while completed sat perfectly still.
Jobs are image processing, 40-90 seconds each. lockDuration is the default 30000, concurrency 5, managed Redis.
Logs show a job starting, then the same job id starting again on a new pod a minute later, sometimes three times over. Eventually a lot of them landed in failed with a stalled message.
Is 90 second work just wrong for this, or is my deploy wrong?
@r2_bucketeer · 3mo ago · 3 replies
Both, but mostly the deploy. Two separate problems that look like one.
The lock. Your job runs three times longer than
lockDuration. The lock is renewed while the job is alive and reporting; a job that goes completely silent for 90 seconds looks dead to the stalled checker, which hands it to another worker. Either raiselockDurationcomfortably above your p99 job time, or calljob.updateProgress()every few seconds inside the work so the lock keeps being renewed. The second is better because it also gives you progress for free.The deploy. Your old pods were killed with jobs in hand. Handle SIGTERM: stop accepting new jobs,
await worker.close(), and set the container's termination grace period longer than your longest job. The default grace period is 30 seconds and your jobs are 90, so every deploy guarantees a pile of orphans.Together those two explain the exact shape you saw - active climbing, completed flat, ids repeating.
Reply
Report
@thermal_theo · 3mo ago
Rough numbers:
lockDurationaround twice your p99,stalledIntervalunder that. And remember every stalled recovery is a full re-run of 90 seconds of image processing, so a bad setting shows up on the compute bill as well as in the logs.Reply
Report
@overlap_owen · 2mo ago
We found ours by putting
activeandcompletedon one chart. Active rising while completed is flat is the whole signature and it is visible in about five seconds. Worth having that graph before you need it.Reply
Report