@nest-boot/bullmq 8.0.4-beta.1 → 8.0.5-beta.1

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/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { BullModule } from "./bullmq.module.js";
2
2
  export * from "./bullmq-module-options.interface.js";
3
+ export { OnQueueEvent } from "./on-queue-event.decorator.js";
4
+ export { OnWorkerEvent } from "./on-worker-event.decorator.js";
3
5
  export { type NestWorkerOptions, Processor } from "./processor.decorator.js";
4
6
  export * from "@nestjs/bullmq";
5
7
  export { QueueEventsListener } from "@nestjs/bullmq";
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  export { BullModule } from "./bullmq.module.js";
2
2
  export * from "./bullmq-module-options.interface.js";
3
+ export { OnQueueEvent } from "./on-queue-event.decorator.js";
4
+ export { OnWorkerEvent } from "./on-worker-event.decorator.js";
3
5
  export { Processor } from "./processor.decorator.js";
4
6
  export * from "@nestjs/bullmq";
5
7
  export { QueueEventsListener } from "@nestjs/bullmq";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,cAAc,sCAAsC,CAAC;AACrD,OAAO,EAA0B,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC7E,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,cAAc,sCAAsC,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAA0B,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC7E,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { QueueEventsListener } from "bullmq";
2
+ /**
3
+ * Listens to a queue event in an independent queue request context.
4
+ *
5
+ * @remarks
6
+ * Use on a method of a singleton `QueueEventsHost` registered with
7
+ * `@QueueEventsListener()`. The event's `jobId` becomes the context ID when
8
+ * present; otherwise an ID is generated. Queue event payloads are not Jobs,
9
+ * so `JOB_REF` is not bound. Handler and middleware failures are logged and
10
+ * suppressed because BullMQ does not await listeners.
11
+ *
12
+ * @param eventName - The queue event to observe
13
+ * @returns A method decorator compatible with Nest's queue event discovery
14
+ */
15
+ export declare function OnQueueEvent(eventName: keyof QueueEventsListener): MethodDecorator;
@@ -0,0 +1,26 @@
1
+ import { OnQueueEvent as BaseOnQueueEvent } from "@nestjs/bullmq";
2
+ import { createContextEventDecorator } from "./utils/create-context-event-decorator.util.js";
3
+ /**
4
+ * Listens to a queue event in an independent queue request context.
5
+ *
6
+ * @remarks
7
+ * Use on a method of a singleton `QueueEventsHost` registered with
8
+ * `@QueueEventsListener()`. The event's `jobId` becomes the context ID when
9
+ * present; otherwise an ID is generated. Queue event payloads are not Jobs,
10
+ * so `JOB_REF` is not bound. Handler and middleware failures are logged and
11
+ * suppressed because BullMQ does not await listeners.
12
+ *
13
+ * @param eventName - The queue event to observe
14
+ * @returns A method decorator compatible with Nest's queue event discovery
15
+ */
16
+ export function OnQueueEvent(eventName) {
17
+ return createContextEventDecorator(eventName, BaseOnQueueEvent(eventName), ([first]) => ({
18
+ id: typeof first === "object" &&
19
+ first !== null &&
20
+ "jobId" in first &&
21
+ typeof first.jobId === "string"
22
+ ? first.jobId
23
+ : undefined,
24
+ }));
25
+ }
26
+ //# sourceMappingURL=on-queue-event.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-queue-event.decorator.js","sourceRoot":"","sources":["../src/on-queue-event.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlE,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAE7F;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAC1B,SAAoC;IAEpC,OAAO,2BAA2B,CAChC,SAAS,EACT,gBAAgB,CAAC,SAAS,CAAC,EAC3B,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACZ,EAAE,EACA,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,OAAO,IAAI,KAAK;YAChB,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;YAC7B,CAAC,CAAC,KAAK,CAAC,KAAK;YACb,CAAC,CAAC,SAAS;KAChB,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { WorkerListener } from "bullmq";
2
+ /**
3
+ * Listens to a worker event in an independent queue request context.
4
+ *
5
+ * @remarks
6
+ * Use on a method of a singleton `WorkerHost` registered with `@Processor()`.
7
+ * Job-bearing events bind `JOB_REF`; `stalled` supplies only the context ID.
8
+ * Events without a job ID use a generated context ID. Handler and middleware
9
+ * failures are logged and suppressed because BullMQ does not await listeners.
10
+ *
11
+ * @param eventName - The worker event to observe
12
+ * @returns A method decorator compatible with Nest's worker event discovery
13
+ */
14
+ export declare function OnWorkerEvent(eventName: keyof WorkerListener): MethodDecorator;
@@ -0,0 +1,30 @@
1
+ import { OnWorkerEvent as BaseOnWorkerEvent } from "@nestjs/bullmq";
2
+ import { createContextEventDecorator } from "./utils/create-context-event-decorator.util.js";
3
+ /**
4
+ * Listens to a worker event in an independent queue request context.
5
+ *
6
+ * @remarks
7
+ * Use on a method of a singleton `WorkerHost` registered with `@Processor()`.
8
+ * Job-bearing events bind `JOB_REF`; `stalled` supplies only the context ID.
9
+ * Events without a job ID use a generated context ID. Handler and middleware
10
+ * failures are logged and suppressed because BullMQ does not await listeners.
11
+ *
12
+ * @param eventName - The worker event to observe
13
+ * @returns A method decorator compatible with Nest's worker event discovery
14
+ */
15
+ export function OnWorkerEvent(eventName) {
16
+ return createContextEventDecorator(eventName, BaseOnWorkerEvent(eventName), ([first]) => {
17
+ switch (eventName) {
18
+ case "active":
19
+ case "completed":
20
+ case "failed":
21
+ case "progress":
22
+ return { job: first };
23
+ case "stalled":
24
+ return { id: first };
25
+ default:
26
+ return {};
27
+ }
28
+ });
29
+ }
30
+ //# sourceMappingURL=on-worker-event.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-worker-event.decorator.js","sourceRoot":"","sources":["../src/on-worker-event.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAE7F;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAC3B,SAA+B;IAE/B,OAAO,2BAA2B,CAChC,SAAS,EACT,iBAAiB,CAAC,SAAS,CAAC,EAC5B,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE;QACV,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,QAAQ,CAAC;YACd,KAAK,WAAW,CAAC;YACjB,KAAK,QAAQ,CAAC;YACd,KAAK,UAAU;gBACb,OAAO,EAAE,GAAG,EAAE,KAAwB,EAAE,CAAC;YAC3C,KAAK,SAAS;gBACZ,OAAO,EAAE,EAAE,EAAE,KAAe,EAAE,CAAC;YACjC;gBACE,OAAO,EAAE,CAAC;QACd,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -10,7 +10,7 @@ export type NestWorkerOptions = Omit<WorkerOptions, "connection"> & Partial<Pick
10
10
  *
11
11
  * @remarks
12
12
  * Wraps the `@nestjs/bullmq` `Processor` decorator to automatically
13
- * create a {@link RequestContext} for each processed job.
13
+ * create a request context for each processed job.
14
14
  *
15
15
  * @param queueName - The name of the queue to process
16
16
  */
@@ -1,18 +1,13 @@
1
1
  /* eslint-disable @typescript-eslint/unified-signatures */
2
- import { RequestContext } from "@nest-boot/request-context";
3
- import { JOB_REF, Processor as BaseProcessor, } from "@nestjs/bullmq";
2
+ import { Processor as BaseProcessor, } from "@nestjs/bullmq";
3
+ import { runInQueueContext } from "./utils/run-in-queue-context.util.js";
4
4
  export function Processor(queueNameOrOptions, maybeWorkerOptions) {
5
5
  return (target) => {
6
6
  const originalProcess = target.prototype.process;
7
7
  if (originalProcess) {
8
8
  target.prototype.process = async function (...args) {
9
9
  const [job] = args;
10
- const ctx = new RequestContext({
11
- id: job.id,
12
- type: "queue",
13
- });
14
- ctx.set(JOB_REF, job);
15
- return await RequestContext.run(ctx, () => originalProcess.apply(this, args));
10
+ return await runInQueueContext({ job }, () => originalProcess.apply(this, args));
16
11
  };
17
12
  }
18
13
  BaseProcessor(queueNameOrOptions, maybeWorkerOptions)(target);
@@ -1 +1 @@
1
- {"version":3,"file":"processor.decorator.js","sourceRoot":"","sources":["../src/processor.decorator.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EACL,OAAO,EACP,SAAS,IAAI,aAAa,GAG3B,MAAM,gBAAgB,CAAC;AAuDxB,MAAM,UAAU,SAAS,CACvB,kBAA8C,EAC9C,kBAAsC;IAEtC,OAAO,CAAC,MAA2B,EAAE,EAAE;QACrC,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC,OAA0B,CAAC;QACpE,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,KAAK,WAC9B,GAAG,IAAiC;gBAEpC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;gBACnB,MAAM,GAAG,GAAG,IAAI,cAAc,CAAC;oBAC7B,EAAE,EAAE,GAAG,CAAC,EAAE;oBACV,IAAI,EAAE,OAAO;iBACd,CAAC,CAAC;gBAEH,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;gBAEtB,OAAO,MAAM,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CACxC,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAClC,CAAC;YACJ,CAAC,CAAC;QACJ,CAAC;QAED,aAAa,CAAC,kBAAyB,EAAE,kBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9E,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"processor.decorator.js","sourceRoot":"","sources":["../src/processor.decorator.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,EACL,SAAS,IAAI,aAAa,GAG3B,MAAM,gBAAgB,CAAC;AAQxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAiDzE,MAAM,UAAU,SAAS,CACvB,kBAA8C,EAC9C,kBAAsC;IAEtC,OAAO,CAAC,MAA2B,EAAE,EAAE;QACrC,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC,OAA0B,CAAC;QACpE,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,KAAK,WAC9B,GAAG,IAAiC;gBAEpC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;gBACnB,OAAO,MAAM,iBAAiB,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,CAC3C,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAClC,CAAC;YACJ,CAAC,CAAC;QACJ,CAAC;QAED,aAAa,CAAC,kBAAyB,EAAE,kBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9E,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type QueueContextOptions } from "./run-in-queue-context.util.js";
2
+ /** Wraps an event callback while preserving Nest's discovery metadata. @internal */
3
+ export declare function createContextEventDecorator(eventName: string, baseDecorator: MethodDecorator, getContextOptions: (args: unknown[]) => QueueContextOptions): MethodDecorator;
@@ -0,0 +1,25 @@
1
+ import { Logger } from "@nestjs/common";
2
+ import { runInQueueContext, } from "./run-in-queue-context.util.js";
3
+ /** Wraps an event callback while preserving Nest's discovery metadata. @internal */
4
+ export function createContextEventDecorator(eventName, baseDecorator, getContextOptions) {
5
+ return (target, propertyKey, descriptor) => {
6
+ const original = descriptor.value;
7
+ const logger = new Logger(`${target.constructor.name}.${String(propertyKey)}`);
8
+ descriptor.value = async function (...args) {
9
+ try {
10
+ return await runInQueueContext(getContextOptions(args), () => original.apply(this, args));
11
+ }
12
+ catch (error) {
13
+ // EventEmitter does not await listeners. Observers must not create
14
+ // unhandled rejections or turn an already completed job into a failure.
15
+ const message = error instanceof Error ? error.message : String(error);
16
+ logger.error(`BullMQ event handler failed (${eventName}): ${message}`, error instanceof Error ? error.stack : undefined);
17
+ }
18
+ };
19
+ for (const key of Reflect.getMetadataKeys(original)) {
20
+ Reflect.defineMetadata(key, Reflect.getMetadata(key, original), descriptor.value);
21
+ }
22
+ return baseDecorator(target, propertyKey, descriptor);
23
+ };
24
+ }
25
+ //# sourceMappingURL=create-context-event-decorator.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-context-event-decorator.util.js","sourceRoot":"","sources":["../../src/utils/create-context-event-decorator.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,OAAO,EAEL,iBAAiB,GAClB,MAAM,gCAAgC,CAAC;AAExC,oFAAoF;AACpF,MAAM,UAAU,2BAA2B,CACzC,SAAiB,EACjB,aAA8B,EAC9B,iBAA2D;IAE3D,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,UAA8B,EAAE,EAAE;QAC7D,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,CAAC,EAAE,CACpD,CAAC;QAEF,UAAU,CAAC,KAAK,GAAG,KAAK,WAAW,GAAG,IAAe;YACnD,IAAI,CAAC;gBACH,OAAO,MAAM,iBAAiB,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAC3D,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAC3B,CAAC;YACJ,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,mEAAmE;gBACnE,wEAAwE;gBACxE,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,MAAM,CAAC,KAAK,CACV,gCAAgC,SAAS,MAAM,OAAO,EAAE,EACxD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CACjD,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpD,OAAO,CAAC,cAAc,CACpB,GAAG,EACH,OAAO,CAAC,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,EAClC,UAAU,CAAC,KAAK,CACjB,CAAC;QACJ,CAAC;QAED,OAAO,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Job } from "bullmq";
2
+ /** Values available when entering a job processor or event handler. @internal */
3
+ export interface QueueContextOptions {
4
+ id?: string;
5
+ job?: Job;
6
+ }
7
+ /** Runs one callback and its middleware in an independent queue context. @internal */
8
+ export declare function runInQueueContext<T>(options: QueueContextOptions, callback: () => T | Promise<T>): Promise<T>;
@@ -0,0 +1,13 @@
1
+ import { RequestContext } from "@nest-boot/request-context";
2
+ import { JOB_REF } from "@nestjs/bullmq";
3
+ /** Runs one callback and its middleware in an independent queue context. @internal */
4
+ export async function runInQueueContext(options, callback) {
5
+ const context = new RequestContext({
6
+ id: options.id ?? options.job?.id,
7
+ type: "queue",
8
+ });
9
+ if (options.job)
10
+ context.set(JOB_REF, options.job);
11
+ return await RequestContext.run(context, callback);
12
+ }
13
+ //# sourceMappingURL=run-in-queue-context.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-in-queue-context.util.js","sourceRoot":"","sources":["../../src/utils/run-in-queue-context.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AASzC,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAA4B,EAC5B,QAA8B;IAE9B,MAAM,OAAO,GAAG,IAAI,cAAc,CAAC;QACjC,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE;QACjC,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,GAAG;QAAE,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAEnD,OAAO,MAAM,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AACrD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nest-boot/bullmq",
3
- "version": "8.0.4-beta.1",
3
+ "version": "8.0.5-beta.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/nest-boot/nest-boot.git",
@@ -38,10 +38,10 @@
38
38
  "typescript": "^6.0.3",
39
39
  "vite-tsconfig-paths": "^5.1.4",
40
40
  "vitest": "^4.1.11",
41
- "@nest-boot/eslint-config": "^8.0.1-beta.0",
42
- "@nest-boot/eslint-plugin": "^8.0.1-beta.0",
43
- "@nest-boot/request-context": "^8.0.1-beta.0",
44
- "@nest-boot/tsconfig": "^8.0.0-beta.4"
41
+ "@nest-boot/eslint-config": "^8.0.2-beta.0",
42
+ "@nest-boot/eslint-plugin": "^8.0.1-beta.1",
43
+ "@nest-boot/tsconfig": "^8.0.0-beta.4",
44
+ "@nest-boot/request-context": "^8.0.2-beta.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@nestjs/bullmq": "^12.0.0",
@@ -50,7 +50,7 @@
50
50
  "bullmq": "^5.0.0",
51
51
  "reflect-metadata": "^0.2.2",
52
52
  "rxjs": "^7.0.0",
53
- "@nest-boot/request-context": "^8.0.1-beta.0"
53
+ "@nest-boot/request-context": "^8.0.2-beta.0"
54
54
  },
55
55
  "publishConfig": {
56
56
  "access": "public"
@@ -73,7 +73,7 @@
73
73
  "./package.json": "./package.json"
74
74
  },
75
75
  "dependencies": {
76
- "@nest-boot/redis": "^8.0.1-beta.1"
76
+ "@nest-boot/redis": "^8.0.2-beta.0"
77
77
  },
78
78
  "scripts": {
79
79
  "build": "tsc -p tsconfig.build.json",