@bymax-one/nest-queue 1.2.12 → 1.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -11,6 +11,124 @@ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
11
11
 
12
12
  ---
13
13
 
14
+ ## [1.2.14] — 2026-11-14
15
+
16
+ Several defaults change in this release, so read the Apply note below. A boot that succeeds, an
17
+ enqueue that Redis answers and a job that completes behave as before.
18
+
19
+ ### Fixed
20
+
21
+ - **A failed Mode B startup no longer leaves a client reconnecting.** When Redis was not ready in
22
+ time the library rejected the boot but kept the `ioredis` client it had opened, which kept
23
+ reconnecting and held the process open. The
24
+ client is now closed on every startup failure.
25
+ - **`connectionReadyTimeoutMs` is a budget, not a first-error limit.** The first connection error
26
+ used to reject the boot at once with the raw `ioredis` error, so a
27
+ Redis restarting during a deploy failed the application. Errors while the client is
28
+ reconnecting are now waited through until the budget ends; the boot then rejects with
29
+ `queue.connection_timeout` whose `details` carry `timeoutMs` and `lastErrorCode` (for example
30
+ `ECONNREFUSED`), never the message, which can name the host. A refused credential
31
+ (`WRONGPASS`, `NOAUTH`) or a client that stopped reconnecting rejects at once with
32
+ `queue.connection_invalid`. Code that matched the raw `ioredis` error of a failed boot should
33
+ match the `QueueException` code instead.
34
+
35
+ ### Changed
36
+
37
+ - **A producer call can no longer hang on a Redis that does not answer.** On the connection the
38
+ library opens, every command now carries a 5 s deadline (`commandTimeoutMs`, or the ioredis
39
+ `commandTimeout` you set), and `enqueue` and `enqueueBulk` reject with `CONNECTION_TIMEOUT` after
40
+ `enqueueTimeoutMs` (10 s) in either connection mode. A command that hits the connection's deadline
41
+ is reported the same way, as `CONNECTION_TIMEOUT` with `details.operation` and `timeoutMs` and the
42
+ original error as `cause`.
43
+ - **The owned connection no longer buffers commands during an outage.** Its offline queue is off, so
44
+ a call made while Redis is down fails at once instead of waiting in memory. Set `options.enableOfflineQueue: true` to keep the old
45
+ behaviour. Worker and QueueEvents connections keep their offline queue and have no command deadline.
46
+ - **A shared client with `maxRetriesPerRequest: null` is reported at boot.** Calls other than `enqueue` and
47
+ `enqueueBulk` then wait for as long as an outage lasts; the library warns and does not refuse.
48
+ - **Shutdown is bounded by one budget, not one per worker.** Workers are closed in parallel and the
49
+ queue-events and connection steps share what is left of `drainTimeoutMs`; a connection that has not
50
+ quit by then is disconnected. With several stuck workers the previous sequence took the budget once
51
+ for each.
52
+ - **`unregister` releases the connection even when the worker's `close()` throws.** It then rethrows
53
+ that error; the registry entry is dropped and the socket closed either way.
54
+ - **`jobTimeoutMs` bounds a handler that never settles.** It is a new worker option with no default,
55
+ a whole number of milliseconds from 1 to 2 147 483 647, as are `commandTimeoutMs` and `enqueueTimeoutMs`.
56
+ When it passes, the job fails with a `queue.job_timeout` error, retries under its `attempts` and
57
+ `backoff`, and its concurrency slot is free again. Handlers receive an `AbortSignal` as a second
58
+ argument, which aborts at that moment or when BullMQ cancels the job (`worker.cancelJob()`,
59
+ `worker.cancelAllJobs()`); closing the worker does not abort it. Before, a hung handler held its
60
+ slot for good and the rest of the queue waited.
61
+ - **Retries are spread by default.** The default backoff now carries 50% jitter: a retry waits between
62
+ half of its exponential delay and the whole of it, so jobs that failed together no longer retry in
63
+ the same instant after an outage. A `backoff` you set yourself is used as given.
64
+ - **`getJobs` reads a bounded window.** At most 1 000 jobs per call, with integer bounds and
65
+ `0 <= start <= end`; an `end` of `-1`, which BullMQ reads as the whole list, is refused with
66
+ `INVALID_OPTIONS`.
67
+
68
+ ### Documentation
69
+
70
+ - **Queue names are documented as keys, not user input**, because each distinct name keeps a queue and
71
+ its Redis resources for the life of the process.
72
+ - **The `prefix` option's JSDoc says it is a namespace, not an access control**.
73
+ - **A timed-out `enqueue` may still have been added**, and the README says to pass a deterministic
74
+ `jobId` for anything that must not run twice.
75
+ - **The README no longer says a Redis outage fails fast regardless of configuration.** It now states
76
+ what bounds a producer call and when the bound does not apply.
77
+
78
+ #### Apply to a derived backend
79
+
80
+ - If you matched ioredis's `Command timed out` error on a producer or inspection call, match
81
+ `CONNECTION_TIMEOUT` instead; the original error is its `cause`.
82
+ - If you rely on an `enqueue` waiting out a Redis outage, it now rejects with `CONNECTION_TIMEOUT`
83
+ after `enqueueTimeoutMs` (the add may still complete in Redis afterwards, so retry with a stable
84
+ `jobId` or `deduplication`); raise the option to keep waiting longer.
85
+ - If you assert exact retry delays, expect them between 50% and 100% of the computed value; set
86
+ `defaultJobOptions.backoff` without `jitter` to keep exact delays.
87
+ - If you call `getJobs` with an `end` of `-1` or a window over 1 000 jobs, those calls now throw
88
+ `INVALID_OPTIONS`. Page through the list with several calls of at most 1 000 jobs, for example
89
+ `getJobs(queue, status, start, start + 499)` in a loop until a page comes back short; the README
90
+ has the loop.
91
+ - Nothing changes until you set `jobTimeoutMs`. If you do, a handler that runs longer than it is
92
+ failed and retried while its own promise keeps running unless it honours the `AbortSignal`, so keep
93
+ handlers idempotent. If you wrap `ProgrammaticWorkerConfig.handler`, accept the new optional second
94
+ parameter.
95
+ - If you relied on shutdown taking up to one `drainTimeoutMs` per stuck worker, it now takes at most
96
+ one in total; raise `drainTimeoutMs` if jobs need longer.
97
+ - If your Mode B code calls a `QueueService` method during a Redis outage and expected it to wait for
98
+ the reconnect, it now rejects at once, since the owned connection has no offline queue; set
99
+ `connection.options.enableOfflineQueue: true` to restore that.
100
+ - A command that takes longer than 5 s on the owned connection (a very large `getJobs` range, for
101
+ example) now rejects; raise `commandTimeoutMs`.
102
+
103
+ ---
104
+
105
+ ## [1.2.13] — 2026-11-12
106
+
107
+ No action required. Measured with `diff -r` of the unpacked 1.2.12 tarball against a fresh
108
+ `npm pack`, the files that differ are `README.md`, `CHANGELOG.md` and the `version` field of
109
+ `package.json`; `dist/` is byte-identical, so the public API, the declaration files and the peer
110
+ ranges are those of 1.2.12.
111
+
112
+ ### Documentation
113
+
114
+ - **The bundle budgets are no longer misquoted.** The Testing section gave "server ≤ 18 KiB brotli,
115
+ shared ≤ 2 500 B"; the gate sets 9 200 B and 440 B. The README now points at `pnpm size` instead of
116
+ restating the numbers.
117
+ - **The tech stack names the real end-to-end dependency.** It listed `@testcontainers/redis`, which
118
+ is not a dependency; the suite uses `testcontainers`.
119
+ - **The Quick Start no longer implies `isGlobal: true` is needed.** It is the default, so the option is
120
+ gone from the snippet and the step says `QueueService` is injectable without it.
121
+ - **The connection-release claim covers only what the library opens.** In Mode A the shared client is
122
+ yours and the library never closes it.
123
+ - **Mode A, Mode B and the connection budget are one Connections section**, the deduplication examples
124
+ are one block, and the msgpackr entry is a short paragraph. API Reference and the error catalog now
125
+ follow Testing, the tech stack is a badge row, and the Quick Start is numbered.
126
+ - **Removed what a reader of the package does not need:** a note about an internal test fixture, a
127
+ history line about a BullMQ state, the pnpm 10 versus 11 narration, and the pointers to the technical
128
+ specification.
129
+
130
+ ---
131
+
14
132
  ## [1.2.12] — 2026-11-09
15
133
 
16
134
  No action required. The public API, the declaration files and the peer ranges are unchanged
@@ -895,7 +1013,9 @@ v6 peer range.
895
1013
 
896
1014
  ---
897
1015
 
898
- [Unreleased]: https://github.com/bymaxone/nest-queue/compare/v1.2.12...HEAD
1016
+ [Unreleased]: https://github.com/bymaxone/nest-queue/compare/v1.2.14...HEAD
1017
+ [1.2.14]: https://github.com/bymaxone/nest-queue/compare/v1.2.13...v1.2.14
1018
+ [1.2.13]: https://github.com/bymaxone/nest-queue/compare/v1.2.12...v1.2.13
899
1019
  [1.2.12]: https://github.com/bymaxone/nest-queue/compare/v1.2.11...v1.2.12
900
1020
  [1.2.11]: https://github.com/bymaxone/nest-queue/compare/v1.2.10...v1.2.11
901
1021
  [1.2.10]: https://github.com/bymaxone/nest-queue/compare/v1.2.9...v1.2.10