Skip to content

feat(queue): honest job-state tracking for the in-memory queue#12

Merged
askalf merged 1 commit into
masterfrom
feat/queue-states
Jun 10, 2026
Merged

feat(queue): honest job-state tracking for the in-memory queue#12
askalf merged 1 commit into
masterfrom
feat/queue-states

Conversation

@askalf

@askalf askalf commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Upgrades the BullMQ-shaped in-memory queue from "fan-out only" to honest job-state tracking, closing the gap between what the API accepts and what it actually does (getJobs(states) ignored its argument; removeOnComplete/removeOnFail were accepted but unused).

Added

  • Full state machine: delayed → waiting → active → completed | failed. A retrying job (backoff timer pending) counts as delayed until re-enqueued.
  • getJobs(states) now honors its argument (unknown names ignored); new getJobCounts(...states) — all five states with no args.
  • removeOnComplete / removeOnFail honored; retained completed/failed history capped at 1000 each (oldest dropped) so a long-lived dev process doesn't leak.
  • Worker#close(force?) waits for in-flight jobs by default (BullMQ semantics); force=true skips the wait. No new jobs start once closing.
  • 'drained' event on the worker — once per drain, not per idle poll. Delayed jobs don't block a drain, matching BullMQ.
  • Queue-level 'completed'/'failed' events mirroring the worker's (a deliberate simplification of BullMQ's separate QueueEvents class).
  • obliterate() cancels pending delay/backoff timers — an obliterated delayed job never runs. queue.close() now delegates to it (previously orphaned timers could fire after close).
  • Exported JobState type.

Tests

45/45 (was 36): state transitions via getJobs/getJobCounts, retry lands in delayed then re-runs, removeOnComplete/Fail, close() provably waits for the in-flight job, close(true) doesn't, drained-fires-once, obliterate cancels delayed, queue-level events.

Release note

No version bump in this PR — v0.1.0's npm publish is pending the NPM_TOKEN fix; this rides under [Unreleased] and ships with the next bump.

- InMemoryQueue tracks the full state machine (delayed -> waiting ->
  active -> completed | failed); retry backoff parks the job as
  delayed via the new _retryLater handshake.
- getJobs(states) honors its argument; new getJobCounts(...states).
- removeOnComplete/removeOnFail honored; retained completed/failed
  history capped at 1000 each (oldest dropped).
- obliterate() cancels pending delay/backoff timers (an obliterated
  delayed job never runs); queue.close() delegates to it.
- Worker close(force?) waits for in-flight jobs by default (BullMQ
  semantics); 'drained' emitted once per drain; queue-level
  'completed'/'failed' events mirror the worker's.
- 9 new tests (45 total). New exported JobState type.
- No version bump: rides with the next release.
@askalf askalf merged commit f4cb015 into master Jun 10, 2026
7 checks passed
@askalf askalf deleted the feat/queue-states branch June 10, 2026 16:26
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