@bymax-one/nest-queue 1.0.7 → 1.0.8
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 +21 -0
- package/README.md +18 -10
- package/dist/server/index.cjs +73 -39
- package/dist/server/index.d.cts +4 -6
- package/dist/server/index.d.ts +4 -6
- package/dist/server/index.mjs +73 -39
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.0.8] — 2026-08-04
|
|
11
|
+
|
|
12
|
+
**Runtime change.** `dist/` differs from `1.0.7`.
|
|
13
|
+
|
|
14
|
+
### Security
|
|
15
|
+
|
|
16
|
+
- The Redis credentials are no longer disclosed when a service that holds them is
|
|
17
|
+
serialized. `connection` moves from a plain field on the resolved options to a
|
|
18
|
+
non-enumerable accessor, and `ConnectionResolver` keeps the ioredis client and the
|
|
19
|
+
consumer's module options in ECMAScript private fields, as do the maps holding the
|
|
20
|
+
`Queue`, `Worker` and `QueueEvents` instances. Those objects were all reachable by
|
|
21
|
+
walking a service: a `url` carries the password inline, and an ioredis instance carries
|
|
22
|
+
`options.password` as a plain field, so `JSON.stringify`, object spread and
|
|
23
|
+
`util.inspect` on `QueueService` emitted the password in plaintext — which is what a
|
|
24
|
+
structured logger does when it renders a provider it was handed, and what an error
|
|
25
|
+
reporter does when it captures the scope of a throw.
|
|
26
|
+
|
|
27
|
+
Reading on purpose is unchanged: `options.connection` resolves as before, and no public
|
|
28
|
+
type or export changed.
|
|
29
|
+
|
|
10
30
|
## [1.0.7] — 2026-08-04
|
|
11
31
|
|
|
12
32
|
**Runtime change.** `dist/` differs from `1.0.6`: the four decorators no longer carry
|
|
@@ -369,6 +389,7 @@ v6 peer range.
|
|
|
369
389
|
|
|
370
390
|
---
|
|
371
391
|
|
|
392
|
+
[1.0.8]: https://github.com/bymaxone/nest-queue/compare/v1.0.7...v1.0.8
|
|
372
393
|
[1.0.7]: https://github.com/bymaxone/nest-queue/compare/v1.0.6...v1.0.7
|
|
373
394
|
[1.0.6]: https://github.com/bymaxone/nest-queue/releases/tag/v1.0.6
|
|
374
395
|
[1.0.5]: https://github.com/bymaxone/nest-queue/releases/tag/v1.0.5
|
package/README.md
CHANGED
|
@@ -711,6 +711,14 @@ message, or an exception payload. `QueueException.details` carries only scalar
|
|
|
711
711
|
configuration values (`{ actualValue, expectedValue, limit, received }`), never a
|
|
712
712
|
connection object and never `job.data`.
|
|
713
713
|
|
|
714
|
+
They are also not reachable by serializing the objects that hold them. The connection is
|
|
715
|
+
attached to the resolved options as a non-enumerable accessor, and the resolver keeps the
|
|
716
|
+
ioredis client — which carries `options.password` as a plain field — in a private field,
|
|
717
|
+
as do the registries that hold the `Queue`, `Worker` and `QueueEvents` instances. So
|
|
718
|
+
`JSON.stringify`, object spread, `util.inspect` and `util.inspect` with `showHidden` all
|
|
719
|
+
come back without credentials, which is what matters when a structured logger renders a
|
|
720
|
+
provider it was handed or an error reporter captures the scope of a throw.
|
|
721
|
+
|
|
714
722
|
### Job data is opaque
|
|
715
723
|
|
|
716
724
|
The library treats `job.data` as a payload to transport, never to inspect. It is never
|
|
@@ -755,16 +763,16 @@ key will do it twice at some point.
|
|
|
755
763
|
|
|
756
764
|
## 🛡️ Security Table
|
|
757
765
|
|
|
758
|
-
| Layer | Implementation
|
|
759
|
-
| ----------------- |
|
|
760
|
-
| Credentials | Injected options only; never read from `process.env`, never logged, never placed in an exception
|
|
761
|
-
| Error payloads | `QueueException.details` restricted to scalar configuration values — no `job.data`, no connection object
|
|
762
|
-
| Job payloads | Treated as opaque; never deep-merged (prototype-pollution guard), never logged
|
|
763
|
-
| Namespacing | `prefix` applied uniformly to `Queue`, `Worker`, `QueueEvents` and `FlowProducer`
|
|
764
|
-
| Connection policy | `maxRetriesPerRequest: null` confined to duplicated consumer connections; producers keep fail-fast retries
|
|
765
|
-
| Delivery | At-least-once with a bounded drain; unacknowledged work is re-queued by BullMQ's stalled check
|
|
766
|
-
| Supply chain | `dependencies: {}`; SHA-pinned Actions, OSV-Scanner, TruffleHog, OpenSSF Scorecard; npm publish over OIDC
|
|
767
|
-
| Input validation | Options validated at bootstrap; cron patterns validated by BullMQ's own parser, never a hand-rolled regex
|
|
766
|
+
| Layer | Implementation |
|
|
767
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
768
|
+
| Credentials | Injected options only; never read from `process.env`, never logged, never placed in an exception; held in a non-enumerable accessor and private fields, so serializing a service omits them |
|
|
769
|
+
| Error payloads | `QueueException.details` restricted to scalar configuration values — no `job.data`, no connection object |
|
|
770
|
+
| Job payloads | Treated as opaque; never deep-merged (prototype-pollution guard), never logged |
|
|
771
|
+
| Namespacing | `prefix` applied uniformly to `Queue`, `Worker`, `QueueEvents` and `FlowProducer` |
|
|
772
|
+
| Connection policy | `maxRetriesPerRequest: null` confined to duplicated consumer connections; producers keep fail-fast retries |
|
|
773
|
+
| Delivery | At-least-once with a bounded drain; unacknowledged work is re-queued by BullMQ's stalled check |
|
|
774
|
+
| Supply chain | `dependencies: {}`; SHA-pinned Actions, OSV-Scanner, TruffleHog, OpenSSF Scorecard; npm publish over OIDC |
|
|
775
|
+
| Input validation | Options validated at bootstrap; cron patterns validated by BullMQ's own parser, never a hand-rolled regex |
|
|
768
776
|
|
|
769
777
|
> [!IMPORTANT]
|
|
770
778
|
> **Delivery is at-least-once, and `prefix` is not an access boundary.** Handlers must be
|
package/dist/server/index.cjs
CHANGED
|
@@ -6,7 +6,12 @@ var ioredis = require('ioredis');
|
|
|
6
6
|
var bullmq = require('bullmq');
|
|
7
7
|
var path = require('path');
|
|
8
8
|
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
9
10
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
|
+
var __typeError = (msg) => {
|
|
12
|
+
throw TypeError(msg);
|
|
13
|
+
};
|
|
14
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
15
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
11
16
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
12
17
|
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
@@ -15,6 +20,11 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
15
20
|
return result;
|
|
16
21
|
};
|
|
17
22
|
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
23
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
24
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
25
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
26
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
27
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
18
28
|
|
|
19
29
|
// src/shared/constants/error-codes.ts
|
|
20
30
|
var QUEUE_ERROR_CODES = {
|
|
@@ -111,8 +121,8 @@ var DEFAULT_SHUTDOWN_DRAIN_TIMEOUT_MS = 3e4;
|
|
|
111
121
|
|
|
112
122
|
// src/server/config/resolved-options.ts
|
|
113
123
|
function applyDefaults(opts) {
|
|
124
|
+
const connection = opts.connection;
|
|
114
125
|
const base = {
|
|
115
|
-
connection: opts.connection,
|
|
116
126
|
defaultJobOptions: { ...DEFAULT_JOB_OPTIONS, ...opts.defaultJobOptions ?? {} },
|
|
117
127
|
prefix: opts.prefix ?? "bull",
|
|
118
128
|
queueOptions: opts.queueOptions ?? {},
|
|
@@ -128,6 +138,11 @@ function applyDefaults(opts) {
|
|
|
128
138
|
connectionReadyTimeoutMs: opts.connectionReadyTimeoutMs ?? DEFAULT_CONNECTION_READY_TIMEOUT_MS
|
|
129
139
|
};
|
|
130
140
|
if (opts.telemetry !== void 0) base.telemetry = opts.telemetry;
|
|
141
|
+
Object.defineProperty(base, "connection", {
|
|
142
|
+
get: () => connection,
|
|
143
|
+
enumerable: false,
|
|
144
|
+
configurable: false
|
|
145
|
+
});
|
|
131
146
|
return Object.freeze(base);
|
|
132
147
|
}
|
|
133
148
|
|
|
@@ -157,34 +172,44 @@ function duplicateConnection(client) {
|
|
|
157
172
|
}
|
|
158
173
|
|
|
159
174
|
// src/server/services/connection-resolver.service.ts
|
|
175
|
+
var _client, _options;
|
|
160
176
|
exports.ConnectionResolver = class ConnectionResolver {
|
|
161
177
|
constructor(options) {
|
|
162
|
-
|
|
178
|
+
/**
|
|
179
|
+
* The resolved Redis client.
|
|
180
|
+
*
|
|
181
|
+
* An ECMAScript private field rather than a TypeScript `private` one, which
|
|
182
|
+
* is erased at runtime: an ioredis instance carries `options.password` as a
|
|
183
|
+
* plain field, so leaving this enumerable would let anything that serializes
|
|
184
|
+
* a service holding this resolver walk into the credentials.
|
|
185
|
+
*/
|
|
186
|
+
__privateAdd(this, _client);
|
|
187
|
+
/** The consumer's module options, which carry the Redis credentials. */
|
|
188
|
+
__privateAdd(this, _options);
|
|
189
|
+
__publicField(this, "mode");
|
|
190
|
+
__privateSet(this, _options, options);
|
|
163
191
|
}
|
|
164
|
-
options;
|
|
165
|
-
client;
|
|
166
|
-
mode;
|
|
167
192
|
/** Resolve and validate the connection. Call once during module bootstrap. */
|
|
168
193
|
async init() {
|
|
169
|
-
const cfg = this.
|
|
194
|
+
const cfg = __privateGet(this, _options).connection;
|
|
170
195
|
if ("client" in cfg) {
|
|
171
196
|
this.initModeA(cfg.client);
|
|
172
197
|
return;
|
|
173
198
|
}
|
|
174
199
|
this.mode = "mode-b-owned";
|
|
175
|
-
this
|
|
200
|
+
__privateSet(this, _client, "url" in cfg ? new ioredis.Redis(cfg.url, { ...cfg.options ?? {}, lazyConnect: false }) : new ioredis.Redis({ ...cfg.options, lazyConnect: false }));
|
|
176
201
|
await this.waitReady(
|
|
177
|
-
this.
|
|
202
|
+
__privateGet(this, _options).connectionReadyTimeoutMs ?? DEFAULT_CONNECTION_READY_TIMEOUT_MS
|
|
178
203
|
);
|
|
179
204
|
}
|
|
180
205
|
/** The resolved Queue-role client. */
|
|
181
206
|
getClient() {
|
|
182
|
-
if (!this
|
|
207
|
+
if (!__privateGet(this, _client)) {
|
|
183
208
|
throw new QueueException(QUEUE_ERROR_CODES.CONNECTION_INVALID, 500, {
|
|
184
209
|
reason: "not initialized"
|
|
185
210
|
});
|
|
186
211
|
}
|
|
187
|
-
return this
|
|
212
|
+
return __privateGet(this, _client);
|
|
188
213
|
}
|
|
189
214
|
/** The resolved connection mode. */
|
|
190
215
|
getMode() {
|
|
@@ -201,8 +226,8 @@ exports.ConnectionResolver = class ConnectionResolver {
|
|
|
201
226
|
}
|
|
202
227
|
/** Close the library-owned connection on shutdown; never touch a BYO client. */
|
|
203
228
|
async teardown() {
|
|
204
|
-
if (this.isOwned() && this
|
|
205
|
-
const client = this
|
|
229
|
+
if (this.isOwned() && __privateGet(this, _client)) {
|
|
230
|
+
const client = __privateGet(this, _client);
|
|
206
231
|
await client.quit().catch(() => {
|
|
207
232
|
client.disconnect();
|
|
208
233
|
});
|
|
@@ -211,7 +236,7 @@ exports.ConnectionResolver = class ConnectionResolver {
|
|
|
211
236
|
/** Validate and adopt a bring-your-own client for the Queue role. */
|
|
212
237
|
initModeA(client) {
|
|
213
238
|
this.mode = "mode-a-byo";
|
|
214
|
-
this
|
|
239
|
+
__privateSet(this, _client, client);
|
|
215
240
|
if (!isClientUsable(client)) {
|
|
216
241
|
throw new QueueException(QUEUE_ERROR_CODES.CONNECTION_INVALID, 500, { status: client.status });
|
|
217
242
|
}
|
|
@@ -249,6 +274,8 @@ exports.ConnectionResolver = class ConnectionResolver {
|
|
|
249
274
|
});
|
|
250
275
|
}
|
|
251
276
|
};
|
|
277
|
+
_client = new WeakMap();
|
|
278
|
+
_options = new WeakMap();
|
|
252
279
|
exports.ConnectionResolver = __decorateClass([
|
|
253
280
|
common.Injectable(),
|
|
254
281
|
__decorateParam(0, common.Inject(BYMAX_QUEUE_OPTIONS))
|
|
@@ -297,15 +324,16 @@ var MAX_BULK_SIZE = 1e3;
|
|
|
297
324
|
function isOperationalError(err) {
|
|
298
325
|
return typeof err?.code === "string";
|
|
299
326
|
}
|
|
327
|
+
var _queues;
|
|
300
328
|
exports.QueueService = class QueueService {
|
|
301
329
|
constructor(connection, options) {
|
|
302
330
|
this.connection = connection;
|
|
303
331
|
this.options = options;
|
|
332
|
+
__publicField(this, "logger", new common.Logger(exports.QueueService.name));
|
|
333
|
+
__privateAdd(this, _queues, /* @__PURE__ */ new Map());
|
|
304
334
|
}
|
|
305
335
|
connection;
|
|
306
336
|
options;
|
|
307
|
-
logger = new common.Logger(exports.QueueService.name);
|
|
308
|
-
queues = /* @__PURE__ */ new Map();
|
|
309
337
|
/**
|
|
310
338
|
* Return the cached `Queue` for `queueName`, or create one with the module
|
|
311
339
|
* defaults applied. Subsequent calls with the same name return the same
|
|
@@ -315,7 +343,7 @@ exports.QueueService = class QueueService {
|
|
|
315
343
|
* @param overrides - Optional per-queue option overrides.
|
|
316
344
|
*/
|
|
317
345
|
getOrCreateQueue(queueName, overrides) {
|
|
318
|
-
const existing = this.
|
|
346
|
+
const existing = __privateGet(this, _queues).get(queueName);
|
|
319
347
|
if (existing) return existing;
|
|
320
348
|
const queue = new bullmq.Queue(queueName, {
|
|
321
349
|
connection: this.connection.getClient(),
|
|
@@ -326,7 +354,7 @@ exports.QueueService = class QueueService {
|
|
|
326
354
|
...overrides
|
|
327
355
|
});
|
|
328
356
|
attachDefaultErrorListener(queue, this.logger, "Queue", queueName);
|
|
329
|
-
this.
|
|
357
|
+
__privateGet(this, _queues).set(queueName, queue);
|
|
330
358
|
return queue;
|
|
331
359
|
}
|
|
332
360
|
/** Resolve the raw cached queue (default generics) for internal delegation. */
|
|
@@ -530,7 +558,7 @@ exports.QueueService = class QueueService {
|
|
|
530
558
|
}
|
|
531
559
|
/** Return a read-only view of the cached queues. */
|
|
532
560
|
getCachedQueues() {
|
|
533
|
-
return this
|
|
561
|
+
return __privateGet(this, _queues);
|
|
534
562
|
}
|
|
535
563
|
/**
|
|
536
564
|
* Close every cached queue (swallowing per-queue errors) and clear the cache.
|
|
@@ -542,12 +570,13 @@ exports.QueueService = class QueueService {
|
|
|
542
570
|
* exists to prevent. `QueueLifecycle` is the only caller.
|
|
543
571
|
*/
|
|
544
572
|
async closeAll() {
|
|
545
|
-
for (const queue of this.
|
|
573
|
+
for (const queue of __privateGet(this, _queues).values()) {
|
|
546
574
|
await queue.close().catch(() => void 0);
|
|
547
575
|
}
|
|
548
|
-
this.
|
|
576
|
+
__privateGet(this, _queues).clear();
|
|
549
577
|
}
|
|
550
578
|
};
|
|
579
|
+
_queues = new WeakMap();
|
|
551
580
|
exports.QueueService = __decorateClass([
|
|
552
581
|
common.Injectable(),
|
|
553
582
|
__decorateParam(0, common.Inject(exports.ConnectionResolver)),
|
|
@@ -704,15 +733,16 @@ exports.MetricsService = class MetricsService {
|
|
|
704
733
|
exports.MetricsService = __decorateClass([
|
|
705
734
|
common.Injectable()
|
|
706
735
|
], exports.MetricsService);
|
|
736
|
+
var _entries;
|
|
707
737
|
exports.WorkerRegistry = class WorkerRegistry {
|
|
708
738
|
constructor(connection, options) {
|
|
709
739
|
this.connection = connection;
|
|
710
740
|
this.options = options;
|
|
741
|
+
__publicField(this, "logger", new common.Logger(exports.WorkerRegistry.name));
|
|
742
|
+
__privateAdd(this, _entries, /* @__PURE__ */ new Map());
|
|
711
743
|
}
|
|
712
744
|
connection;
|
|
713
745
|
options;
|
|
714
|
-
logger = new common.Logger(exports.WorkerRegistry.name);
|
|
715
|
-
entries = /* @__PURE__ */ new Map();
|
|
716
746
|
/**
|
|
717
747
|
* Register an in-process worker with a handler function. The BullMQ `Worker`
|
|
718
748
|
* constructor is synchronous — no Redis handshake is performed at registration
|
|
@@ -743,7 +773,7 @@ exports.WorkerRegistry = class WorkerRegistry {
|
|
|
743
773
|
});
|
|
744
774
|
}
|
|
745
775
|
attachDefaultErrorListener(worker, this.logger, "Worker", queueName);
|
|
746
|
-
this.
|
|
776
|
+
__privateGet(this, _entries).set(queueName, { worker, connection: conn });
|
|
747
777
|
return worker;
|
|
748
778
|
}
|
|
749
779
|
/**
|
|
@@ -782,7 +812,7 @@ exports.WorkerRegistry = class WorkerRegistry {
|
|
|
782
812
|
});
|
|
783
813
|
}
|
|
784
814
|
attachDefaultErrorListener(worker, this.logger, "Worker", queueName);
|
|
785
|
-
this.
|
|
815
|
+
__privateGet(this, _entries).set(queueName, { worker, connection: conn });
|
|
786
816
|
return worker;
|
|
787
817
|
}
|
|
788
818
|
/**
|
|
@@ -793,11 +823,11 @@ exports.WorkerRegistry = class WorkerRegistry {
|
|
|
793
823
|
* @param queueName - The queue whose worker should be removed.
|
|
794
824
|
*/
|
|
795
825
|
async unregister(queueName) {
|
|
796
|
-
const entry = this.
|
|
826
|
+
const entry = __privateGet(this, _entries).get(queueName);
|
|
797
827
|
if (!entry) return;
|
|
798
828
|
await entry.worker.close();
|
|
799
829
|
await this.closeConnection(entry.connection);
|
|
800
|
-
this.
|
|
830
|
+
__privateGet(this, _entries).delete(queueName);
|
|
801
831
|
}
|
|
802
832
|
/**
|
|
803
833
|
* Returns the queue names of all currently registered workers.
|
|
@@ -805,7 +835,7 @@ exports.WorkerRegistry = class WorkerRegistry {
|
|
|
805
835
|
* @returns An immutable array of queue names.
|
|
806
836
|
*/
|
|
807
837
|
list() {
|
|
808
|
-
return Array.from(this.
|
|
838
|
+
return Array.from(__privateGet(this, _entries).keys());
|
|
809
839
|
}
|
|
810
840
|
/**
|
|
811
841
|
* Returns a read-only view of the registered workers keyed by queue name.
|
|
@@ -815,7 +845,7 @@ exports.WorkerRegistry = class WorkerRegistry {
|
|
|
815
845
|
*/
|
|
816
846
|
getAll() {
|
|
817
847
|
return new Map(
|
|
818
|
-
Array.from(this
|
|
848
|
+
Array.from(__privateGet(this, _entries), ([name, entry]) => [name, entry.worker])
|
|
819
849
|
);
|
|
820
850
|
}
|
|
821
851
|
/**
|
|
@@ -828,7 +858,7 @@ exports.WorkerRegistry = class WorkerRegistry {
|
|
|
828
858
|
*/
|
|
829
859
|
getConnections() {
|
|
830
860
|
return new Map(
|
|
831
|
-
Array.from(this
|
|
861
|
+
Array.from(__privateGet(this, _entries), ([name, entry]) => [name, entry.connection])
|
|
832
862
|
);
|
|
833
863
|
}
|
|
834
864
|
/**
|
|
@@ -851,7 +881,7 @@ exports.WorkerRegistry = class WorkerRegistry {
|
|
|
851
881
|
* @throws {QueueException} `DUPLICATE_PROCESSOR` if the queue is already registered.
|
|
852
882
|
*/
|
|
853
883
|
guardDuplicate(queueName) {
|
|
854
|
-
if (this.
|
|
884
|
+
if (__privateGet(this, _entries).has(queueName)) {
|
|
855
885
|
throw new QueueException(QUEUE_ERROR_CODES.DUPLICATE_PROCESSOR, 500, { queueName });
|
|
856
886
|
}
|
|
857
887
|
}
|
|
@@ -960,21 +990,23 @@ exports.WorkerRegistry = class WorkerRegistry {
|
|
|
960
990
|
return result;
|
|
961
991
|
}
|
|
962
992
|
};
|
|
993
|
+
_entries = new WeakMap();
|
|
963
994
|
exports.WorkerRegistry = __decorateClass([
|
|
964
995
|
common.Injectable(),
|
|
965
996
|
__decorateParam(0, common.Inject(exports.ConnectionResolver)),
|
|
966
997
|
__decorateParam(1, common.Inject(BYMAX_QUEUE_RESOLVED_OPTIONS))
|
|
967
998
|
], exports.WorkerRegistry);
|
|
999
|
+
var _events, _connections;
|
|
968
1000
|
exports.QueueEventsRegistry = class QueueEventsRegistry {
|
|
969
1001
|
constructor(connection, options) {
|
|
970
1002
|
this.connection = connection;
|
|
971
1003
|
this.options = options;
|
|
1004
|
+
__publicField(this, "logger", new common.Logger(exports.QueueEventsRegistry.name));
|
|
1005
|
+
__privateAdd(this, _events, /* @__PURE__ */ new Map());
|
|
1006
|
+
__privateAdd(this, _connections, /* @__PURE__ */ new Map());
|
|
972
1007
|
}
|
|
973
1008
|
connection;
|
|
974
1009
|
options;
|
|
975
|
-
logger = new common.Logger(exports.QueueEventsRegistry.name);
|
|
976
|
-
events = /* @__PURE__ */ new Map();
|
|
977
|
-
connections = /* @__PURE__ */ new Map();
|
|
978
1010
|
/**
|
|
979
1011
|
* Returns the cached `QueueEvents` for `queueName`, creating one on first
|
|
980
1012
|
* call. Subsequent calls for the same name return the same instance without
|
|
@@ -984,7 +1016,7 @@ exports.QueueEventsRegistry = class QueueEventsRegistry {
|
|
|
984
1016
|
* @returns The `QueueEvents` instance for the queue.
|
|
985
1017
|
*/
|
|
986
1018
|
getOrCreate(queueName) {
|
|
987
|
-
const existing = this.
|
|
1019
|
+
const existing = __privateGet(this, _events).get(queueName);
|
|
988
1020
|
if (existing) return existing;
|
|
989
1021
|
const conn = duplicateConnection(this.connection.getClient());
|
|
990
1022
|
let qe;
|
|
@@ -995,8 +1027,8 @@ exports.QueueEventsRegistry = class QueueEventsRegistry {
|
|
|
995
1027
|
throw err;
|
|
996
1028
|
}
|
|
997
1029
|
attachDefaultErrorListener(qe, this.logger, "QueueEvents", queueName);
|
|
998
|
-
this.
|
|
999
|
-
this.
|
|
1030
|
+
__privateGet(this, _events).set(queueName, qe);
|
|
1031
|
+
__privateGet(this, _connections).set(queueName, conn);
|
|
1000
1032
|
return qe;
|
|
1001
1033
|
}
|
|
1002
1034
|
/**
|
|
@@ -1005,7 +1037,7 @@ exports.QueueEventsRegistry = class QueueEventsRegistry {
|
|
|
1005
1037
|
* @returns An immutable array of queue names.
|
|
1006
1038
|
*/
|
|
1007
1039
|
list() {
|
|
1008
|
-
return Array.from(this.
|
|
1040
|
+
return Array.from(__privateGet(this, _events).keys());
|
|
1009
1041
|
}
|
|
1010
1042
|
/**
|
|
1011
1043
|
* Returns the live `QueueEvents` map. Intended for the shutdown orchestrator.
|
|
@@ -1013,7 +1045,7 @@ exports.QueueEventsRegistry = class QueueEventsRegistry {
|
|
|
1013
1045
|
* @returns A read-only view of the internal map.
|
|
1014
1046
|
*/
|
|
1015
1047
|
getAll() {
|
|
1016
|
-
return this
|
|
1048
|
+
return __privateGet(this, _events);
|
|
1017
1049
|
}
|
|
1018
1050
|
/**
|
|
1019
1051
|
* Returns a read-only view of the duplicated connections the library opened
|
|
@@ -1029,9 +1061,11 @@ exports.QueueEventsRegistry = class QueueEventsRegistry {
|
|
|
1029
1061
|
* @returns A read-only snapshot of queue name to duplicated connection.
|
|
1030
1062
|
*/
|
|
1031
1063
|
getConnections() {
|
|
1032
|
-
return new Map(this
|
|
1064
|
+
return new Map(__privateGet(this, _connections));
|
|
1033
1065
|
}
|
|
1034
1066
|
};
|
|
1067
|
+
_events = new WeakMap();
|
|
1068
|
+
_connections = new WeakMap();
|
|
1035
1069
|
exports.QueueEventsRegistry = __decorateClass([
|
|
1036
1070
|
common.Injectable(),
|
|
1037
1071
|
__decorateParam(0, common.Inject(exports.ConnectionResolver)),
|
package/dist/server/index.d.cts
CHANGED
|
@@ -354,8 +354,7 @@ type JobSchedulerRepeatOptions = {
|
|
|
354
354
|
* for `ready`, closing it on shutdown.
|
|
355
355
|
*/
|
|
356
356
|
declare class ConnectionResolver {
|
|
357
|
-
private
|
|
358
|
-
private client;
|
|
357
|
+
#private;
|
|
359
358
|
private mode;
|
|
360
359
|
constructor(options: BymaxQueueModuleOptions);
|
|
361
360
|
/** Resolve and validate the connection. Call once during module bootstrap. */
|
|
@@ -390,10 +389,10 @@ type CleanableStatus = 'completed' | 'failed' | 'delayed' | 'wait' | 'active' |
|
|
|
390
389
|
* enqueueing, inspection, metrics, and lifecycle control.
|
|
391
390
|
*/
|
|
392
391
|
declare class QueueService {
|
|
392
|
+
#private;
|
|
393
393
|
private readonly connection;
|
|
394
394
|
private readonly options;
|
|
395
395
|
private readonly logger;
|
|
396
|
-
private readonly queues;
|
|
397
396
|
constructor(connection: ConnectionResolver, options: ResolvedQueueOptions);
|
|
398
397
|
/**
|
|
399
398
|
* Return the cached `Queue` for `queueName`, or create one with the module
|
|
@@ -792,10 +791,10 @@ interface SandboxedWorkerConfig {
|
|
|
792
791
|
* })
|
|
793
792
|
*/
|
|
794
793
|
declare class WorkerRegistry {
|
|
794
|
+
#private;
|
|
795
795
|
private readonly connection;
|
|
796
796
|
private readonly options;
|
|
797
797
|
private readonly logger;
|
|
798
|
-
private readonly entries;
|
|
799
798
|
constructor(connection: ConnectionResolver, options: ResolvedQueueOptions);
|
|
800
799
|
/**
|
|
801
800
|
* Register an in-process worker with a handler function. The BullMQ `Worker`
|
|
@@ -937,11 +936,10 @@ declare class WorkerRegistry {
|
|
|
937
936
|
* qe.on('completed', ({ jobId }) => console.log(jobId))
|
|
938
937
|
*/
|
|
939
938
|
declare class QueueEventsRegistry {
|
|
939
|
+
#private;
|
|
940
940
|
private readonly connection;
|
|
941
941
|
private readonly options;
|
|
942
942
|
private readonly logger;
|
|
943
|
-
private readonly events;
|
|
944
|
-
private readonly connections;
|
|
945
943
|
constructor(connection: ConnectionResolver, options: ResolvedQueueOptions);
|
|
946
944
|
/**
|
|
947
945
|
* Returns the cached `QueueEvents` for `queueName`, creating one on first
|
package/dist/server/index.d.ts
CHANGED
|
@@ -354,8 +354,7 @@ type JobSchedulerRepeatOptions = {
|
|
|
354
354
|
* for `ready`, closing it on shutdown.
|
|
355
355
|
*/
|
|
356
356
|
declare class ConnectionResolver {
|
|
357
|
-
private
|
|
358
|
-
private client;
|
|
357
|
+
#private;
|
|
359
358
|
private mode;
|
|
360
359
|
constructor(options: BymaxQueueModuleOptions);
|
|
361
360
|
/** Resolve and validate the connection. Call once during module bootstrap. */
|
|
@@ -390,10 +389,10 @@ type CleanableStatus = 'completed' | 'failed' | 'delayed' | 'wait' | 'active' |
|
|
|
390
389
|
* enqueueing, inspection, metrics, and lifecycle control.
|
|
391
390
|
*/
|
|
392
391
|
declare class QueueService {
|
|
392
|
+
#private;
|
|
393
393
|
private readonly connection;
|
|
394
394
|
private readonly options;
|
|
395
395
|
private readonly logger;
|
|
396
|
-
private readonly queues;
|
|
397
396
|
constructor(connection: ConnectionResolver, options: ResolvedQueueOptions);
|
|
398
397
|
/**
|
|
399
398
|
* Return the cached `Queue` for `queueName`, or create one with the module
|
|
@@ -792,10 +791,10 @@ interface SandboxedWorkerConfig {
|
|
|
792
791
|
* })
|
|
793
792
|
*/
|
|
794
793
|
declare class WorkerRegistry {
|
|
794
|
+
#private;
|
|
795
795
|
private readonly connection;
|
|
796
796
|
private readonly options;
|
|
797
797
|
private readonly logger;
|
|
798
|
-
private readonly entries;
|
|
799
798
|
constructor(connection: ConnectionResolver, options: ResolvedQueueOptions);
|
|
800
799
|
/**
|
|
801
800
|
* Register an in-process worker with a handler function. The BullMQ `Worker`
|
|
@@ -937,11 +936,10 @@ declare class WorkerRegistry {
|
|
|
937
936
|
* qe.on('completed', ({ jobId }) => console.log(jobId))
|
|
938
937
|
*/
|
|
939
938
|
declare class QueueEventsRegistry {
|
|
939
|
+
#private;
|
|
940
940
|
private readonly connection;
|
|
941
941
|
private readonly options;
|
|
942
942
|
private readonly logger;
|
|
943
|
-
private readonly events;
|
|
944
|
-
private readonly connections;
|
|
945
943
|
constructor(connection: ConnectionResolver, options: ResolvedQueueOptions);
|
|
946
944
|
/**
|
|
947
945
|
* Returns the cached `QueueEvents` for `queueName`, creating one on first
|
package/dist/server/index.mjs
CHANGED
|
@@ -4,7 +4,12 @@ import { Redis } from 'ioredis';
|
|
|
4
4
|
import { Worker, QueueEvents, Queue, FlowProducer } from 'bullmq';
|
|
5
5
|
import { isAbsolute, extname } from 'path';
|
|
6
6
|
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
7
8
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
|
+
var __typeError = (msg) => {
|
|
10
|
+
throw TypeError(msg);
|
|
11
|
+
};
|
|
12
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
13
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
9
14
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
10
15
|
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
@@ -13,6 +18,11 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
13
18
|
return result;
|
|
14
19
|
};
|
|
15
20
|
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
21
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
22
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
23
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
24
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
25
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
16
26
|
|
|
17
27
|
// src/shared/constants/error-codes.ts
|
|
18
28
|
var QUEUE_ERROR_CODES = {
|
|
@@ -109,8 +119,8 @@ var DEFAULT_SHUTDOWN_DRAIN_TIMEOUT_MS = 3e4;
|
|
|
109
119
|
|
|
110
120
|
// src/server/config/resolved-options.ts
|
|
111
121
|
function applyDefaults(opts) {
|
|
122
|
+
const connection = opts.connection;
|
|
112
123
|
const base = {
|
|
113
|
-
connection: opts.connection,
|
|
114
124
|
defaultJobOptions: { ...DEFAULT_JOB_OPTIONS, ...opts.defaultJobOptions ?? {} },
|
|
115
125
|
prefix: opts.prefix ?? "bull",
|
|
116
126
|
queueOptions: opts.queueOptions ?? {},
|
|
@@ -126,6 +136,11 @@ function applyDefaults(opts) {
|
|
|
126
136
|
connectionReadyTimeoutMs: opts.connectionReadyTimeoutMs ?? DEFAULT_CONNECTION_READY_TIMEOUT_MS
|
|
127
137
|
};
|
|
128
138
|
if (opts.telemetry !== void 0) base.telemetry = opts.telemetry;
|
|
139
|
+
Object.defineProperty(base, "connection", {
|
|
140
|
+
get: () => connection,
|
|
141
|
+
enumerable: false,
|
|
142
|
+
configurable: false
|
|
143
|
+
});
|
|
129
144
|
return Object.freeze(base);
|
|
130
145
|
}
|
|
131
146
|
|
|
@@ -155,34 +170,44 @@ function duplicateConnection(client) {
|
|
|
155
170
|
}
|
|
156
171
|
|
|
157
172
|
// src/server/services/connection-resolver.service.ts
|
|
173
|
+
var _client, _options;
|
|
158
174
|
var ConnectionResolver = class {
|
|
159
175
|
constructor(options) {
|
|
160
|
-
|
|
176
|
+
/**
|
|
177
|
+
* The resolved Redis client.
|
|
178
|
+
*
|
|
179
|
+
* An ECMAScript private field rather than a TypeScript `private` one, which
|
|
180
|
+
* is erased at runtime: an ioredis instance carries `options.password` as a
|
|
181
|
+
* plain field, so leaving this enumerable would let anything that serializes
|
|
182
|
+
* a service holding this resolver walk into the credentials.
|
|
183
|
+
*/
|
|
184
|
+
__privateAdd(this, _client);
|
|
185
|
+
/** The consumer's module options, which carry the Redis credentials. */
|
|
186
|
+
__privateAdd(this, _options);
|
|
187
|
+
__publicField(this, "mode");
|
|
188
|
+
__privateSet(this, _options, options);
|
|
161
189
|
}
|
|
162
|
-
options;
|
|
163
|
-
client;
|
|
164
|
-
mode;
|
|
165
190
|
/** Resolve and validate the connection. Call once during module bootstrap. */
|
|
166
191
|
async init() {
|
|
167
|
-
const cfg = this.
|
|
192
|
+
const cfg = __privateGet(this, _options).connection;
|
|
168
193
|
if ("client" in cfg) {
|
|
169
194
|
this.initModeA(cfg.client);
|
|
170
195
|
return;
|
|
171
196
|
}
|
|
172
197
|
this.mode = "mode-b-owned";
|
|
173
|
-
this
|
|
198
|
+
__privateSet(this, _client, "url" in cfg ? new Redis(cfg.url, { ...cfg.options ?? {}, lazyConnect: false }) : new Redis({ ...cfg.options, lazyConnect: false }));
|
|
174
199
|
await this.waitReady(
|
|
175
|
-
this.
|
|
200
|
+
__privateGet(this, _options).connectionReadyTimeoutMs ?? DEFAULT_CONNECTION_READY_TIMEOUT_MS
|
|
176
201
|
);
|
|
177
202
|
}
|
|
178
203
|
/** The resolved Queue-role client. */
|
|
179
204
|
getClient() {
|
|
180
|
-
if (!this
|
|
205
|
+
if (!__privateGet(this, _client)) {
|
|
181
206
|
throw new QueueException(QUEUE_ERROR_CODES.CONNECTION_INVALID, 500, {
|
|
182
207
|
reason: "not initialized"
|
|
183
208
|
});
|
|
184
209
|
}
|
|
185
|
-
return this
|
|
210
|
+
return __privateGet(this, _client);
|
|
186
211
|
}
|
|
187
212
|
/** The resolved connection mode. */
|
|
188
213
|
getMode() {
|
|
@@ -199,8 +224,8 @@ var ConnectionResolver = class {
|
|
|
199
224
|
}
|
|
200
225
|
/** Close the library-owned connection on shutdown; never touch a BYO client. */
|
|
201
226
|
async teardown() {
|
|
202
|
-
if (this.isOwned() && this
|
|
203
|
-
const client = this
|
|
227
|
+
if (this.isOwned() && __privateGet(this, _client)) {
|
|
228
|
+
const client = __privateGet(this, _client);
|
|
204
229
|
await client.quit().catch(() => {
|
|
205
230
|
client.disconnect();
|
|
206
231
|
});
|
|
@@ -209,7 +234,7 @@ var ConnectionResolver = class {
|
|
|
209
234
|
/** Validate and adopt a bring-your-own client for the Queue role. */
|
|
210
235
|
initModeA(client) {
|
|
211
236
|
this.mode = "mode-a-byo";
|
|
212
|
-
this
|
|
237
|
+
__privateSet(this, _client, client);
|
|
213
238
|
if (!isClientUsable(client)) {
|
|
214
239
|
throw new QueueException(QUEUE_ERROR_CODES.CONNECTION_INVALID, 500, { status: client.status });
|
|
215
240
|
}
|
|
@@ -247,6 +272,8 @@ var ConnectionResolver = class {
|
|
|
247
272
|
});
|
|
248
273
|
}
|
|
249
274
|
};
|
|
275
|
+
_client = new WeakMap();
|
|
276
|
+
_options = new WeakMap();
|
|
250
277
|
ConnectionResolver = __decorateClass([
|
|
251
278
|
Injectable(),
|
|
252
279
|
__decorateParam(0, Inject(BYMAX_QUEUE_OPTIONS))
|
|
@@ -295,15 +322,16 @@ var MAX_BULK_SIZE = 1e3;
|
|
|
295
322
|
function isOperationalError(err) {
|
|
296
323
|
return typeof err?.code === "string";
|
|
297
324
|
}
|
|
325
|
+
var _queues;
|
|
298
326
|
var QueueService = class {
|
|
299
327
|
constructor(connection, options) {
|
|
300
328
|
this.connection = connection;
|
|
301
329
|
this.options = options;
|
|
330
|
+
__publicField(this, "logger", new Logger(QueueService.name));
|
|
331
|
+
__privateAdd(this, _queues, /* @__PURE__ */ new Map());
|
|
302
332
|
}
|
|
303
333
|
connection;
|
|
304
334
|
options;
|
|
305
|
-
logger = new Logger(QueueService.name);
|
|
306
|
-
queues = /* @__PURE__ */ new Map();
|
|
307
335
|
/**
|
|
308
336
|
* Return the cached `Queue` for `queueName`, or create one with the module
|
|
309
337
|
* defaults applied. Subsequent calls with the same name return the same
|
|
@@ -313,7 +341,7 @@ var QueueService = class {
|
|
|
313
341
|
* @param overrides - Optional per-queue option overrides.
|
|
314
342
|
*/
|
|
315
343
|
getOrCreateQueue(queueName, overrides) {
|
|
316
|
-
const existing = this.
|
|
344
|
+
const existing = __privateGet(this, _queues).get(queueName);
|
|
317
345
|
if (existing) return existing;
|
|
318
346
|
const queue = new Queue(queueName, {
|
|
319
347
|
connection: this.connection.getClient(),
|
|
@@ -324,7 +352,7 @@ var QueueService = class {
|
|
|
324
352
|
...overrides
|
|
325
353
|
});
|
|
326
354
|
attachDefaultErrorListener(queue, this.logger, "Queue", queueName);
|
|
327
|
-
this.
|
|
355
|
+
__privateGet(this, _queues).set(queueName, queue);
|
|
328
356
|
return queue;
|
|
329
357
|
}
|
|
330
358
|
/** Resolve the raw cached queue (default generics) for internal delegation. */
|
|
@@ -528,7 +556,7 @@ var QueueService = class {
|
|
|
528
556
|
}
|
|
529
557
|
/** Return a read-only view of the cached queues. */
|
|
530
558
|
getCachedQueues() {
|
|
531
|
-
return this
|
|
559
|
+
return __privateGet(this, _queues);
|
|
532
560
|
}
|
|
533
561
|
/**
|
|
534
562
|
* Close every cached queue (swallowing per-queue errors) and clear the cache.
|
|
@@ -540,12 +568,13 @@ var QueueService = class {
|
|
|
540
568
|
* exists to prevent. `QueueLifecycle` is the only caller.
|
|
541
569
|
*/
|
|
542
570
|
async closeAll() {
|
|
543
|
-
for (const queue of this.
|
|
571
|
+
for (const queue of __privateGet(this, _queues).values()) {
|
|
544
572
|
await queue.close().catch(() => void 0);
|
|
545
573
|
}
|
|
546
|
-
this.
|
|
574
|
+
__privateGet(this, _queues).clear();
|
|
547
575
|
}
|
|
548
576
|
};
|
|
577
|
+
_queues = new WeakMap();
|
|
549
578
|
QueueService = __decorateClass([
|
|
550
579
|
Injectable(),
|
|
551
580
|
__decorateParam(0, Inject(ConnectionResolver)),
|
|
@@ -702,15 +731,16 @@ var MetricsService = class {
|
|
|
702
731
|
MetricsService = __decorateClass([
|
|
703
732
|
Injectable()
|
|
704
733
|
], MetricsService);
|
|
734
|
+
var _entries;
|
|
705
735
|
var WorkerRegistry = class {
|
|
706
736
|
constructor(connection, options) {
|
|
707
737
|
this.connection = connection;
|
|
708
738
|
this.options = options;
|
|
739
|
+
__publicField(this, "logger", new Logger(WorkerRegistry.name));
|
|
740
|
+
__privateAdd(this, _entries, /* @__PURE__ */ new Map());
|
|
709
741
|
}
|
|
710
742
|
connection;
|
|
711
743
|
options;
|
|
712
|
-
logger = new Logger(WorkerRegistry.name);
|
|
713
|
-
entries = /* @__PURE__ */ new Map();
|
|
714
744
|
/**
|
|
715
745
|
* Register an in-process worker with a handler function. The BullMQ `Worker`
|
|
716
746
|
* constructor is synchronous — no Redis handshake is performed at registration
|
|
@@ -741,7 +771,7 @@ var WorkerRegistry = class {
|
|
|
741
771
|
});
|
|
742
772
|
}
|
|
743
773
|
attachDefaultErrorListener(worker, this.logger, "Worker", queueName);
|
|
744
|
-
this.
|
|
774
|
+
__privateGet(this, _entries).set(queueName, { worker, connection: conn });
|
|
745
775
|
return worker;
|
|
746
776
|
}
|
|
747
777
|
/**
|
|
@@ -780,7 +810,7 @@ var WorkerRegistry = class {
|
|
|
780
810
|
});
|
|
781
811
|
}
|
|
782
812
|
attachDefaultErrorListener(worker, this.logger, "Worker", queueName);
|
|
783
|
-
this.
|
|
813
|
+
__privateGet(this, _entries).set(queueName, { worker, connection: conn });
|
|
784
814
|
return worker;
|
|
785
815
|
}
|
|
786
816
|
/**
|
|
@@ -791,11 +821,11 @@ var WorkerRegistry = class {
|
|
|
791
821
|
* @param queueName - The queue whose worker should be removed.
|
|
792
822
|
*/
|
|
793
823
|
async unregister(queueName) {
|
|
794
|
-
const entry = this.
|
|
824
|
+
const entry = __privateGet(this, _entries).get(queueName);
|
|
795
825
|
if (!entry) return;
|
|
796
826
|
await entry.worker.close();
|
|
797
827
|
await this.closeConnection(entry.connection);
|
|
798
|
-
this.
|
|
828
|
+
__privateGet(this, _entries).delete(queueName);
|
|
799
829
|
}
|
|
800
830
|
/**
|
|
801
831
|
* Returns the queue names of all currently registered workers.
|
|
@@ -803,7 +833,7 @@ var WorkerRegistry = class {
|
|
|
803
833
|
* @returns An immutable array of queue names.
|
|
804
834
|
*/
|
|
805
835
|
list() {
|
|
806
|
-
return Array.from(this.
|
|
836
|
+
return Array.from(__privateGet(this, _entries).keys());
|
|
807
837
|
}
|
|
808
838
|
/**
|
|
809
839
|
* Returns a read-only view of the registered workers keyed by queue name.
|
|
@@ -813,7 +843,7 @@ var WorkerRegistry = class {
|
|
|
813
843
|
*/
|
|
814
844
|
getAll() {
|
|
815
845
|
return new Map(
|
|
816
|
-
Array.from(this
|
|
846
|
+
Array.from(__privateGet(this, _entries), ([name, entry]) => [name, entry.worker])
|
|
817
847
|
);
|
|
818
848
|
}
|
|
819
849
|
/**
|
|
@@ -826,7 +856,7 @@ var WorkerRegistry = class {
|
|
|
826
856
|
*/
|
|
827
857
|
getConnections() {
|
|
828
858
|
return new Map(
|
|
829
|
-
Array.from(this
|
|
859
|
+
Array.from(__privateGet(this, _entries), ([name, entry]) => [name, entry.connection])
|
|
830
860
|
);
|
|
831
861
|
}
|
|
832
862
|
/**
|
|
@@ -849,7 +879,7 @@ var WorkerRegistry = class {
|
|
|
849
879
|
* @throws {QueueException} `DUPLICATE_PROCESSOR` if the queue is already registered.
|
|
850
880
|
*/
|
|
851
881
|
guardDuplicate(queueName) {
|
|
852
|
-
if (this.
|
|
882
|
+
if (__privateGet(this, _entries).has(queueName)) {
|
|
853
883
|
throw new QueueException(QUEUE_ERROR_CODES.DUPLICATE_PROCESSOR, 500, { queueName });
|
|
854
884
|
}
|
|
855
885
|
}
|
|
@@ -958,21 +988,23 @@ var WorkerRegistry = class {
|
|
|
958
988
|
return result;
|
|
959
989
|
}
|
|
960
990
|
};
|
|
991
|
+
_entries = new WeakMap();
|
|
961
992
|
WorkerRegistry = __decorateClass([
|
|
962
993
|
Injectable(),
|
|
963
994
|
__decorateParam(0, Inject(ConnectionResolver)),
|
|
964
995
|
__decorateParam(1, Inject(BYMAX_QUEUE_RESOLVED_OPTIONS))
|
|
965
996
|
], WorkerRegistry);
|
|
997
|
+
var _events, _connections;
|
|
966
998
|
var QueueEventsRegistry = class {
|
|
967
999
|
constructor(connection, options) {
|
|
968
1000
|
this.connection = connection;
|
|
969
1001
|
this.options = options;
|
|
1002
|
+
__publicField(this, "logger", new Logger(QueueEventsRegistry.name));
|
|
1003
|
+
__privateAdd(this, _events, /* @__PURE__ */ new Map());
|
|
1004
|
+
__privateAdd(this, _connections, /* @__PURE__ */ new Map());
|
|
970
1005
|
}
|
|
971
1006
|
connection;
|
|
972
1007
|
options;
|
|
973
|
-
logger = new Logger(QueueEventsRegistry.name);
|
|
974
|
-
events = /* @__PURE__ */ new Map();
|
|
975
|
-
connections = /* @__PURE__ */ new Map();
|
|
976
1008
|
/**
|
|
977
1009
|
* Returns the cached `QueueEvents` for `queueName`, creating one on first
|
|
978
1010
|
* call. Subsequent calls for the same name return the same instance without
|
|
@@ -982,7 +1014,7 @@ var QueueEventsRegistry = class {
|
|
|
982
1014
|
* @returns The `QueueEvents` instance for the queue.
|
|
983
1015
|
*/
|
|
984
1016
|
getOrCreate(queueName) {
|
|
985
|
-
const existing = this.
|
|
1017
|
+
const existing = __privateGet(this, _events).get(queueName);
|
|
986
1018
|
if (existing) return existing;
|
|
987
1019
|
const conn = duplicateConnection(this.connection.getClient());
|
|
988
1020
|
let qe;
|
|
@@ -993,8 +1025,8 @@ var QueueEventsRegistry = class {
|
|
|
993
1025
|
throw err;
|
|
994
1026
|
}
|
|
995
1027
|
attachDefaultErrorListener(qe, this.logger, "QueueEvents", queueName);
|
|
996
|
-
this.
|
|
997
|
-
this.
|
|
1028
|
+
__privateGet(this, _events).set(queueName, qe);
|
|
1029
|
+
__privateGet(this, _connections).set(queueName, conn);
|
|
998
1030
|
return qe;
|
|
999
1031
|
}
|
|
1000
1032
|
/**
|
|
@@ -1003,7 +1035,7 @@ var QueueEventsRegistry = class {
|
|
|
1003
1035
|
* @returns An immutable array of queue names.
|
|
1004
1036
|
*/
|
|
1005
1037
|
list() {
|
|
1006
|
-
return Array.from(this.
|
|
1038
|
+
return Array.from(__privateGet(this, _events).keys());
|
|
1007
1039
|
}
|
|
1008
1040
|
/**
|
|
1009
1041
|
* Returns the live `QueueEvents` map. Intended for the shutdown orchestrator.
|
|
@@ -1011,7 +1043,7 @@ var QueueEventsRegistry = class {
|
|
|
1011
1043
|
* @returns A read-only view of the internal map.
|
|
1012
1044
|
*/
|
|
1013
1045
|
getAll() {
|
|
1014
|
-
return this
|
|
1046
|
+
return __privateGet(this, _events);
|
|
1015
1047
|
}
|
|
1016
1048
|
/**
|
|
1017
1049
|
* Returns a read-only view of the duplicated connections the library opened
|
|
@@ -1027,9 +1059,11 @@ var QueueEventsRegistry = class {
|
|
|
1027
1059
|
* @returns A read-only snapshot of queue name to duplicated connection.
|
|
1028
1060
|
*/
|
|
1029
1061
|
getConnections() {
|
|
1030
|
-
return new Map(this
|
|
1062
|
+
return new Map(__privateGet(this, _connections));
|
|
1031
1063
|
}
|
|
1032
1064
|
};
|
|
1065
|
+
_events = new WeakMap();
|
|
1066
|
+
_connections = new WeakMap();
|
|
1033
1067
|
QueueEventsRegistry = __decorateClass([
|
|
1034
1068
|
Injectable(),
|
|
1035
1069
|
__decorateParam(0, Inject(ConnectionResolver)),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bymax-one/nest-queue",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "NestJS dynamic module wrapping BullMQ — typed jobs, flows, job schedulers, deduplication, OpenTelemetry, graceful shutdown",
|
|
5
5
|
"author": "Bymax One <support@bymax.one>",
|
|
6
6
|
"license": "MIT",
|