@bymax-one/nest-queue 1.2.9 → 1.2.11

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.
@@ -1,5 +1,5 @@
1
1
  import * as _nestjs_common from '@nestjs/common';
2
- import { ModuleMetadata, Type, DynamicModule, OnModuleDestroy, HttpException, HttpStatus } from '@nestjs/common';
2
+ import { ModuleMetadata, Type, DynamicModule, OnModuleDestroy, OnApplicationShutdown, HttpException, HttpStatus } from '@nestjs/common';
3
3
  import { JobsOptions, QueueOptions, Telemetry, BulkJobOptions, Queue, Job, FlowJob, JobNode, FlowProducer, Worker, QueueEvents } from 'bullmq';
4
4
  export { FlowJob, FlowProducer, Job, JobNode, JobSchedulerJson, JobsOptions, Queue, QueueEvents, SandboxedJob, Telemetry, Worker } from 'bullmq';
5
5
  import { Redis, RedisOptions } from 'ioredis';
@@ -453,7 +453,11 @@ declare class QueueService {
453
453
  * @param jobName - Job identifier used by `@Process` to dispatch.
454
454
  * @param data - Typed job payload.
455
455
  * @param options - Per-job BullMQ options (priority, delay, `jobId`, `deduplication`, ...).
456
- * @returns The created job.
456
+ * @returns The job BullMQ returned. When a custom `jobId` already exists, or a `deduplication`
457
+ * rule keeps the job already there (one with `replace` swaps it for the new job), nothing new
458
+ * is added: BullMQ answers with the id of the EXISTING job and the data and options of THIS
459
+ * call, so the returned object does not describe what is stored. Call
460
+ * {@link QueueService.getJob} when you need the stored job.
457
461
  * @example Throttle: at most one reindex per term every 5 seconds. Both variable
458
462
  * fields are percent-encoded, so no other tenant/term pair can build this key.
459
463
  * const dedupId = `${encodeURIComponent(tenantId)}:reindex:${encodeURIComponent(term)}`
@@ -470,6 +474,9 @@ declare class QueueService {
470
474
  *
471
475
  * @param queueName - Target queue.
472
476
  * @param jobs - Job descriptors (length must not exceed the bulk size cap).
477
+ * @returns The jobs BullMQ returned, in input order. An entry whose custom `jobId` already
478
+ * exists is not added again: it carries the EXISTING id with the data of this call, as for
479
+ * {@link QueueService.enqueue}.
473
480
  */
474
481
  enqueueBulk<TData = unknown, TResult = unknown>(queueName: string, jobs: readonly BulkJob<TData>[]): Promise<TypedJob<TData, TResult>[]>;
475
482
  /**
@@ -501,9 +508,9 @@ declare class QueueService {
501
508
  * never duplicates it. This supersedes the repeatable-jobs surface removed in
502
509
  * BullMQ v6.
503
510
  *
504
- * The schedule is structurally validated first; the cron string itself is
505
- * parsed by BullMQ at registration time, and a parse failure is rethrown as
506
- * `INVALID_REPEAT_OPTIONS` (400).
511
+ * The schedule is validated first, and a cron pattern BullMQ's parser rejects
512
+ * is `INVALID_REPEAT_OPTIONS` (400) before Redis is asked; any other failure
513
+ * propagates as it is.
507
514
  *
508
515
  * @param queueName - Target queue.
509
516
  * @param schedulerId - Stable, unique scheduler identifier (the upsert key).
@@ -607,6 +614,9 @@ declare class FlowService {
607
614
  *
608
615
  * @param flow - Flow tree definition.
609
616
  * @returns The root `JobNode` containing the created job and its children.
617
+ * A job whose custom `jobId` already exists is not added again: its node carries the EXISTING
618
+ * id with the data of this call, so the tree does not describe what is stored; call
619
+ * `QueueService.getJob` when you need it.
610
620
  * @throws {QueueException} `FLOW_DISABLED` (503) when flows are not enabled.
611
621
  */
612
622
  add(flow: FlowJob): Promise<JobNode>;
@@ -615,6 +625,7 @@ declare class FlowService {
615
625
  *
616
626
  * @param flows - Flow tree definitions.
617
627
  * @returns The root `JobNode` for each flow, in input order.
628
+ * A job whose custom `jobId` already exists is not added again; see {@link FlowService.add}.
618
629
  * @throws {QueueException} `FLOW_DISABLED` (503) when flows are not enabled.
619
630
  */
620
631
  addBulk(flows: readonly FlowJob[]): Promise<JobNode[]>;
@@ -1002,9 +1013,12 @@ declare class QueueEventsRegistry {
1002
1013
 
1003
1014
  /**
1004
1015
  * @fileoverview `QueueLifecycle` — the single, ordered graceful-shutdown
1005
- * orchestrator. On `onModuleDestroy` it drains every worker within a bounded
1006
- * budget, then tears down queue-events, the connections the library opened,
1007
- * the flow producer, the cached queues, and finally the Queue-role connection.
1016
+ * orchestrator, split across the two NestJS hooks that bracket the HTTP server.
1017
+ * On `onModuleDestroy` it stops consumption: it drains every worker within a
1018
+ * bounded budget, then closes queue-events and the connections the library
1019
+ * opened for them. On `onApplicationShutdown`, which NestJS runs only after the
1020
+ * HTTP server has stopped, it releases what a request can still be using: the
1021
+ * flow producer, the cached queues, and finally the Queue-role connection.
1008
1022
  *
1009
1023
  * Delivery is at-least-once: when a worker exceeds the drain budget it is
1010
1024
  * force-closed and its in-flight job becomes `stalled` and is retried by another
@@ -1017,16 +1031,22 @@ declare class QueueEventsRegistry {
1017
1031
  /**
1018
1032
  * Ordered graceful-shutdown service. Implementing the protocol in one place
1019
1033
  * guarantees the teardown order — workers drain first, then queue-events, then
1020
- * the duplicated connections, then the flow producer, the queues, and finally
1021
- * the Queue-role connection. Every step swallows its own errors so a single
1022
- * failure never aborts the rest of the sequence.
1034
+ * the duplicated connections; once the HTTP server has stopped, the flow
1035
+ * producer, the queues, and finally the Queue-role connection. Every step
1036
+ * swallows its own errors so a single failure never aborts the rest of the
1037
+ * sequence.
1038
+ *
1039
+ * Why two hooks: NestJS runs `onModuleDestroy` before it stops the HTTP server,
1040
+ * so a request that is still being served can enqueue a job after that hook has
1041
+ * returned. The producer side (queues, flow producer, Queue-role connection)
1042
+ * therefore waits for `onApplicationShutdown`, while consumption stops early.
1023
1043
  *
1024
1044
  * Connection ownership: in **Mode B** the library-owned Queue-role client is
1025
1045
  * quit by the connection resolver; in **Mode A** that step is a no-op and only
1026
1046
  * the duplicated worker/queue-events connections the library created are closed
1027
1047
  * — the consumer's shared client is never touched.
1028
1048
  */
1029
- declare class QueueLifecycle implements OnModuleDestroy {
1049
+ declare class QueueLifecycle implements OnModuleDestroy, OnApplicationShutdown {
1030
1050
  private readonly workers;
1031
1051
  private readonly events;
1032
1052
  private readonly queues;
@@ -1034,12 +1054,22 @@ declare class QueueLifecycle implements OnModuleDestroy {
1034
1054
  private readonly connection;
1035
1055
  private readonly resolved;
1036
1056
  private readonly logger;
1057
+ private startedAt;
1058
+ private forcedWorkers;
1037
1059
  constructor(workers: WorkerRegistry, events: QueueEventsRegistry, queues: QueueService, flow: FlowService, connection: ConnectionResolver, resolved: ResolvedQueueOptions);
1038
1060
  /**
1039
- * Run the ordered shutdown sequence. Called by NestJS when the application
1040
- * context closes (e.g. on `SIGTERM` with shutdown hooks enabled).
1061
+ * Stop consumption: drain the workers within the bounded budget, then close
1062
+ * queue-events and the connections the library opened for them. Called by
1063
+ * NestJS when the application context closes (e.g. on `SIGTERM` with shutdown
1064
+ * hooks enabled), before the HTTP server stops.
1041
1065
  */
1042
1066
  onModuleDestroy(): Promise<void>;
1067
+ /**
1068
+ * Release the producer side once the HTTP server has stopped: the optional
1069
+ * queue drain, the flow producer, the cached queues, and the Queue-role
1070
+ * connection, then log the total shutdown time.
1071
+ */
1072
+ onApplicationShutdown(): Promise<void>;
1043
1073
  /**
1044
1074
  * Close every worker with a bounded drain, force-closing any that exceed the
1045
1075
  * budget. Returns the number of workers that had to be force-closed.
@@ -1,5 +1,5 @@
1
1
  import * as _nestjs_common from '@nestjs/common';
2
- import { ModuleMetadata, Type, DynamicModule, OnModuleDestroy, HttpException, HttpStatus } from '@nestjs/common';
2
+ import { ModuleMetadata, Type, DynamicModule, OnModuleDestroy, OnApplicationShutdown, HttpException, HttpStatus } from '@nestjs/common';
3
3
  import { JobsOptions, QueueOptions, Telemetry, BulkJobOptions, Queue, Job, FlowJob, JobNode, FlowProducer, Worker, QueueEvents } from 'bullmq';
4
4
  export { FlowJob, FlowProducer, Job, JobNode, JobSchedulerJson, JobsOptions, Queue, QueueEvents, SandboxedJob, Telemetry, Worker } from 'bullmq';
5
5
  import { Redis, RedisOptions } from 'ioredis';
@@ -453,7 +453,11 @@ declare class QueueService {
453
453
  * @param jobName - Job identifier used by `@Process` to dispatch.
454
454
  * @param data - Typed job payload.
455
455
  * @param options - Per-job BullMQ options (priority, delay, `jobId`, `deduplication`, ...).
456
- * @returns The created job.
456
+ * @returns The job BullMQ returned. When a custom `jobId` already exists, or a `deduplication`
457
+ * rule keeps the job already there (one with `replace` swaps it for the new job), nothing new
458
+ * is added: BullMQ answers with the id of the EXISTING job and the data and options of THIS
459
+ * call, so the returned object does not describe what is stored. Call
460
+ * {@link QueueService.getJob} when you need the stored job.
457
461
  * @example Throttle: at most one reindex per term every 5 seconds. Both variable
458
462
  * fields are percent-encoded, so no other tenant/term pair can build this key.
459
463
  * const dedupId = `${encodeURIComponent(tenantId)}:reindex:${encodeURIComponent(term)}`
@@ -470,6 +474,9 @@ declare class QueueService {
470
474
  *
471
475
  * @param queueName - Target queue.
472
476
  * @param jobs - Job descriptors (length must not exceed the bulk size cap).
477
+ * @returns The jobs BullMQ returned, in input order. An entry whose custom `jobId` already
478
+ * exists is not added again: it carries the EXISTING id with the data of this call, as for
479
+ * {@link QueueService.enqueue}.
473
480
  */
474
481
  enqueueBulk<TData = unknown, TResult = unknown>(queueName: string, jobs: readonly BulkJob<TData>[]): Promise<TypedJob<TData, TResult>[]>;
475
482
  /**
@@ -501,9 +508,9 @@ declare class QueueService {
501
508
  * never duplicates it. This supersedes the repeatable-jobs surface removed in
502
509
  * BullMQ v6.
503
510
  *
504
- * The schedule is structurally validated first; the cron string itself is
505
- * parsed by BullMQ at registration time, and a parse failure is rethrown as
506
- * `INVALID_REPEAT_OPTIONS` (400).
511
+ * The schedule is validated first, and a cron pattern BullMQ's parser rejects
512
+ * is `INVALID_REPEAT_OPTIONS` (400) before Redis is asked; any other failure
513
+ * propagates as it is.
507
514
  *
508
515
  * @param queueName - Target queue.
509
516
  * @param schedulerId - Stable, unique scheduler identifier (the upsert key).
@@ -607,6 +614,9 @@ declare class FlowService {
607
614
  *
608
615
  * @param flow - Flow tree definition.
609
616
  * @returns The root `JobNode` containing the created job and its children.
617
+ * A job whose custom `jobId` already exists is not added again: its node carries the EXISTING
618
+ * id with the data of this call, so the tree does not describe what is stored; call
619
+ * `QueueService.getJob` when you need it.
610
620
  * @throws {QueueException} `FLOW_DISABLED` (503) when flows are not enabled.
611
621
  */
612
622
  add(flow: FlowJob): Promise<JobNode>;
@@ -615,6 +625,7 @@ declare class FlowService {
615
625
  *
616
626
  * @param flows - Flow tree definitions.
617
627
  * @returns The root `JobNode` for each flow, in input order.
628
+ * A job whose custom `jobId` already exists is not added again; see {@link FlowService.add}.
618
629
  * @throws {QueueException} `FLOW_DISABLED` (503) when flows are not enabled.
619
630
  */
620
631
  addBulk(flows: readonly FlowJob[]): Promise<JobNode[]>;
@@ -1002,9 +1013,12 @@ declare class QueueEventsRegistry {
1002
1013
 
1003
1014
  /**
1004
1015
  * @fileoverview `QueueLifecycle` — the single, ordered graceful-shutdown
1005
- * orchestrator. On `onModuleDestroy` it drains every worker within a bounded
1006
- * budget, then tears down queue-events, the connections the library opened,
1007
- * the flow producer, the cached queues, and finally the Queue-role connection.
1016
+ * orchestrator, split across the two NestJS hooks that bracket the HTTP server.
1017
+ * On `onModuleDestroy` it stops consumption: it drains every worker within a
1018
+ * bounded budget, then closes queue-events and the connections the library
1019
+ * opened for them. On `onApplicationShutdown`, which NestJS runs only after the
1020
+ * HTTP server has stopped, it releases what a request can still be using: the
1021
+ * flow producer, the cached queues, and finally the Queue-role connection.
1008
1022
  *
1009
1023
  * Delivery is at-least-once: when a worker exceeds the drain budget it is
1010
1024
  * force-closed and its in-flight job becomes `stalled` and is retried by another
@@ -1017,16 +1031,22 @@ declare class QueueEventsRegistry {
1017
1031
  /**
1018
1032
  * Ordered graceful-shutdown service. Implementing the protocol in one place
1019
1033
  * guarantees the teardown order — workers drain first, then queue-events, then
1020
- * the duplicated connections, then the flow producer, the queues, and finally
1021
- * the Queue-role connection. Every step swallows its own errors so a single
1022
- * failure never aborts the rest of the sequence.
1034
+ * the duplicated connections; once the HTTP server has stopped, the flow
1035
+ * producer, the queues, and finally the Queue-role connection. Every step
1036
+ * swallows its own errors so a single failure never aborts the rest of the
1037
+ * sequence.
1038
+ *
1039
+ * Why two hooks: NestJS runs `onModuleDestroy` before it stops the HTTP server,
1040
+ * so a request that is still being served can enqueue a job after that hook has
1041
+ * returned. The producer side (queues, flow producer, Queue-role connection)
1042
+ * therefore waits for `onApplicationShutdown`, while consumption stops early.
1023
1043
  *
1024
1044
  * Connection ownership: in **Mode B** the library-owned Queue-role client is
1025
1045
  * quit by the connection resolver; in **Mode A** that step is a no-op and only
1026
1046
  * the duplicated worker/queue-events connections the library created are closed
1027
1047
  * — the consumer's shared client is never touched.
1028
1048
  */
1029
- declare class QueueLifecycle implements OnModuleDestroy {
1049
+ declare class QueueLifecycle implements OnModuleDestroy, OnApplicationShutdown {
1030
1050
  private readonly workers;
1031
1051
  private readonly events;
1032
1052
  private readonly queues;
@@ -1034,12 +1054,22 @@ declare class QueueLifecycle implements OnModuleDestroy {
1034
1054
  private readonly connection;
1035
1055
  private readonly resolved;
1036
1056
  private readonly logger;
1057
+ private startedAt;
1058
+ private forcedWorkers;
1037
1059
  constructor(workers: WorkerRegistry, events: QueueEventsRegistry, queues: QueueService, flow: FlowService, connection: ConnectionResolver, resolved: ResolvedQueueOptions);
1038
1060
  /**
1039
- * Run the ordered shutdown sequence. Called by NestJS when the application
1040
- * context closes (e.g. on `SIGTERM` with shutdown hooks enabled).
1061
+ * Stop consumption: drain the workers within the bounded budget, then close
1062
+ * queue-events and the connections the library opened for them. Called by
1063
+ * NestJS when the application context closes (e.g. on `SIGTERM` with shutdown
1064
+ * hooks enabled), before the HTTP server stops.
1041
1065
  */
1042
1066
  onModuleDestroy(): Promise<void>;
1067
+ /**
1068
+ * Release the producer side once the HTTP server has stopped: the optional
1069
+ * queue drain, the flow producer, the cached queues, and the Queue-role
1070
+ * connection, then log the total shutdown time.
1071
+ */
1072
+ onApplicationShutdown(): Promise<void>;
1043
1073
  /**
1044
1074
  * Close every worker with a bounded drain, force-closing any that exceed the
1045
1075
  * budget. Returns the number of workers that had to be force-closed.