Skip to content

fix: give each BullMQ stalled check a trace of its own (v0.1.3) - #4

Merged
victor-carv merged 1 commit into
mainfrom
fix/bullmq-stalled-check-root
Oct 21, 2026
Merged

victor-carv merged 1 commit into
mainfrom
fix/bullmq-stalled-check-root

Conversation

@victor-carv

Copy link
Copy Markdown
Member

What

BullMQ's Worker.startStalledCheckTimer starts the stalled-check loop inside its own span and returns without awaiting it. The loop keeps that span's context, so every moveStalledJobsToWait (every 30 s, per queue) and its evalsha became a child of one startStalledCheckTimer trace for the life of the process.

In Backbone production one such trace held 9,163 spans over about a day and a half (2026-10-18 21:28 → 2026-10-20 11:38 UTC), then crossed Tempo's 5 MB per-trace limit. Since then Tempo refuses its spans at a steady 720/h (tempo_discarded_spans_total{reason="trace_too_large"}), which fires the platform's IngestionRejected alert.

The BullMQ adapter is now wrapped (src/bullmq-loops.ts): moveStalledJobsToWait starts on the root context, so each check is a small trace of its own with its Redis call inside it. Every other operation, and a job's propagated parent (an explicit context from BullMQ), is unchanged. Version 0.1.3.

Tests

  • src/__tests__/bullmq-loops.test.ts drives BullMQ's own exported trace helper with the real BullMQOtel adapter, in the same shape as startStalledCheckTimer. Without the fix the three checks share one trace (fails); with it each has its own, and the Redis call stays inside it.
  • The other two cases pin what must not change: an operation under an active span keeps it as parent, and a consumer keeps the producer's propagated trace.
  • pnpm typecheck, pnpm test (981 passed), pnpm build with dist/ committed.

After merge

Tag v0.1.3, then bump Backbone's pin.

🤖 Generated with Claude Code

BullMQ's Worker starts its stalled-check loop inside the startStalledCheckTimer span, so
every moveStalledJobsToWait (every 30 s per queue) and its redis call joined that one
trace for the life of the process. In Backbone production each such trace reached
Tempo's 5 MB per-trace limit after about a day and a half, and Tempo then refused its
spans (trace_too_large).

The BullMQ adapter now starts moveStalledJobsToWait on the root context unless BullMQ
passes an explicit parent. Every other operation, and a job's propagated parent, is
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@victor-carv
victor-carv merged commit 8430410 into main Oct 21, 2026
1 check passed
@victor-carv
victor-carv deleted the fix/bullmq-stalled-check-root branch October 21, 2026 02:21
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