@bymax-one/nest-queue 1.0.0

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 ADDED
@@ -0,0 +1,123 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@bymax-one/nest-queue` are documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/);
6
+ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ---
9
+
10
+ ## [1.0.0] — 2026-07-30
11
+
12
+ First public release. The library is feature-complete for the surface described
13
+ in `docs/technical_specification.md`, holds 100% line/branch/function/statement
14
+ coverage, and ships with zero runtime dependencies.
15
+
16
+ ### Added
17
+
18
+ - `BymaxQueueModule.forRoot()` and `.forRootAsync()` dynamic module (built on
19
+ `ConfigurableModuleBuilder`; `isGlobal` mapped to `DynamicModule.global` via `setExtras`)
20
+ - `QueueService` with typed `enqueue` (native `deduplication` options), `enqueueBulk`,
21
+ `getJob`, `getJobs`, `getMetrics`, `pauseQueue`/`resumeQueue`/`cleanQueue`, and Job
22
+ Schedulers `upsertJobScheduler`/`removeJobScheduler`/`getJobSchedulers`
23
+ - `@Processor`, `@Process`, `@OnWorkerEvent` (worker-local, full `Job`), `@OnQueueEvent`
24
+ (global) decorators plus automatic discovery via `DiscoveryService`; `job.updateProgress()`
25
+ and progress event support
26
+ - `WorkerRegistry` programmatic API, including `registerSandboxed` for file-based
27
+ out-of-process processors
28
+ - `FlowService` (opt-in via `options.flows.enabled`)
29
+ - `MetricsService` with TTL cache (opt-in via `options.metrics.enabled`)
30
+ - Optional OpenTelemetry `telemetry` passthrough (via `bullmq-otel`, an optional peer dep)
31
+ - `QueueLifecycle` bounded graceful-shutdown protocol (bounded drain via `Promise.race` +
32
+ `worker.close(true)`, optional drain, Redis disconnect on Mode B); at-least-once semantics
33
+ documented
34
+ - Dual-mode connection (Mode A: bring-your-own ioredis / Mode B: lib-owned), with per-role
35
+ `maxRetriesPerRequest` policy applied automatically
36
+ - Subpaths: `.` (server), `./shared` (zero-dep types and constants)
37
+ - `'error'` as a subscribable `@OnQueueEvent` name. It carries a real `Error`
38
+ instance rather than the serialized payload every other queue event delivers,
39
+ because it reports a connection fault rather than a job transition
40
+ - Peer deps: `@nestjs/common ^11`, `@nestjs/core ^11`, `bullmq ^5.16`, `ioredis ^5`,
41
+ `reflect-metadata ^0.2`; optional `bullmq-otel ^1`
42
+ - E2E tests with Testcontainers Redis
43
+
44
+ ### Fixed
45
+
46
+ - **The configured `prefix` now reaches every BullMQ object.** Only the producer
47
+ `Queue` received `options.prefix`; the `Worker`, `QueueEvents` and `FlowProducer`
48
+ were constructed without it and fell back to BullMQ's default `bull` prefix. With
49
+ any non-default prefix, producers and consumers diverged onto separate keyspaces —
50
+ workers never consumed jobs, event listeners never fired, and flow jobs were
51
+ enqueued where no worker polled. Nothing threw.
52
+ - **Explicit `@Inject` on every injectable constructor parameter.** The package
53
+ ships as a tsup/esbuild bundle, and esbuild does not emit
54
+ `emitDecoratorMetadata`. Providers resolved purely by reflected type metadata
55
+ (`QueueService`, `WorkerRegistry`, `QueueEventsRegistry`,
56
+ `ProcessorDiscoveryService`, `QueueLifecycle`) could not be instantiated from
57
+ the built `dist` by a consumer's Nest container.
58
+ - **The `exports` map hands CommonJS consumers CommonJS declarations.** With
59
+ `"type": "module"`, TypeScript reads a bare `.d.ts` as ESM, so a `require()`
60
+ consumer landed on ESM declarations. `types` is now declared per condition,
61
+ `main`/`module`/`types` are present for legacy resolution, `./package.json` is
62
+ exported, and the package passes `attw` at the strict profile.
63
+
64
+ - **Every BullMQ emitter the library creates carries a fallback `error` listener.**
65
+ `Queue`, `Worker`, `QueueEvents` and `FlowProducer` extend Node's `EventEmitter`,
66
+ where emitting `'error'` with no listener **throws** rather than being delivered.
67
+ The library constructs all four on the consumer's behalf, so a transient Redis
68
+ fault surfaced as an uncaught exception in an application that never asked for
69
+ the emitter. The fallback logs and does not consume the event — an
70
+ `@OnWorkerEvent('error')` or `@OnQueueEvent('error')` handler still runs.
71
+ - **One owner for shutdown.** `QueueService`, `FlowService` and `ConnectionResolver`
72
+ each exposed `onModuleDestroy`, and NestJS binds lifecycle hooks by method name,
73
+ so Nest invoked them on its own schedule while `QueueLifecycle` also called two
74
+ of them inside its ordered sequence: the flow producer closed twice, and queues
75
+ could close before the bounded drain finished with them. They now expose plain
76
+ methods — `QueueService.closeAll()`, `FlowService.close()`,
77
+ `ConnectionResolver.teardown()` — and `QueueLifecycle` is the only lifecycle hook.
78
+ - **Operational failures no longer masquerade as a bad cron.** `upsertJobScheduler`
79
+ wrapped every failure in `INVALID_REPEAT_OPTIONS` with HTTP 400 and "pattern must
80
+ be a valid cron expression", so an unreachable Redis was reported as a client
81
+ mistake — with a status telling the caller not to retry. Faults carrying a string
82
+ `code` now propagate untouched.
83
+ - **A malformed `repeat` raises the documented error instead of a `TypeError`.**
84
+ The union forbids it for a TypeScript caller, but plain JavaScript and any
85
+ payload cast from `unknown` reached the `in` operator unchecked. `null`,
86
+ `undefined`, strings, numbers and arrays are rejected as
87
+ `INVALID_REPEAT_OPTIONS`, as is a blank `pattern`.
88
+ - **`QueueEventsRegistry.getConnections()` returns a copy.** `ReadonlyMap` is a
89
+ compile-time claim only; the live registry could be cast and mutated.
90
+
91
+ ### Security
92
+
93
+ - Release pipeline gated behind a manual-approval environment, with SHA-pinned
94
+ actions, tag/version verification, and OIDC provenance from the second release
95
+ onward.
96
+
97
+ ---
98
+
99
+ ## BullMQ version policy
100
+
101
+ ### 1.x — floor `bullmq ^5.16.0`
102
+
103
+ The `1.x` series floors `peerDependencies.bullmq` at `^5.16.0`, the release that
104
+ introduced the Job Schedulers API (`upsertJobScheduler`/`removeJobScheduler`/`getJobSchedulers`).
105
+ Current recommended peer: `5.79.1`.
106
+
107
+ ### Forward compatibility with BullMQ v6
108
+
109
+ This library is **forward-compatible with BullMQ v6 by design**. It exclusively uses
110
+ Job Schedulers for recurring jobs and never calls the removed `addRepeatable`/`removeRepeatable`
111
+ API, so no public-API break is expected on promotion to v6.
112
+
113
+ **Promotion trigger.** When the E2E suite is green on both the v5 and v6 matrix, the peer
114
+ range will be widened to `^5.16.0 || ^6.0.0` in a minor release. No adapter is needed because
115
+ the recurring-jobs surface is unchanged.
116
+
117
+ **Fallback.** If another API used by the library breaks in BullMQ v6 without a trivial adapter,
118
+ a parallel branch will keep the `1.x` line on `^5.16` only, and a `2.x` series will track the
119
+ v6 peer range.
120
+
121
+ ---
122
+
123
+ [1.0.0]: https://github.com/bymaxone/nest-queue/releases/tag/v1.0.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bymax One
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.