@nicnocquee/dataqueue 1.34.0 → 1.35.0-beta.20260224110011
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/ai/docs-content.json +27 -15
- package/ai/rules/advanced.md +78 -1
- package/ai/rules/basic.md +73 -3
- package/ai/rules/react-dashboard.md +5 -1
- package/ai/skills/dataqueue-advanced/SKILL.md +181 -0
- package/ai/skills/dataqueue-core/SKILL.md +109 -3
- package/ai/skills/dataqueue-react/SKILL.md +19 -7
- package/dist/index.cjs +1168 -173
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +394 -13
- package/dist/index.d.ts +394 -13
- package/dist/index.js +1168 -173
- package/dist/index.js.map +1 -1
- package/migrations/1781200000005_add_retry_config_to_job_queue.sql +17 -0
- package/migrations/1781200000006_add_output_to_job_queue.sql +3 -0
- package/migrations/1781200000007_add_group_fields_to_job_queue.sql +16 -0
- package/package.json +1 -1
- package/src/backend.ts +37 -3
- package/src/backends/postgres.ts +458 -76
- package/src/backends/redis-scripts.ts +273 -37
- package/src/backends/redis.test.ts +753 -0
- package/src/backends/redis.ts +253 -15
- package/src/db-util.ts +1 -1
- package/src/index.test.ts +811 -12
- package/src/index.ts +106 -14
- package/src/processor.test.ts +18 -0
- package/src/processor.ts +147 -49
- package/src/queue.test.ts +584 -0
- package/src/queue.ts +22 -3
- package/src/supervisor.test.ts +340 -0
- package/src/supervisor.ts +177 -0
- package/src/types.ts +353 -3
package/src/types.ts
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
// Utility type for job type keys
|
|
2
2
|
export type JobType<PayloadMap> = keyof PayloadMap & string;
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Abstract database client interface for transactional job creation.
|
|
6
|
+
* Compatible with `pg.Pool`, `pg.PoolClient`, `pg.Client`, or any object
|
|
7
|
+
* that exposes a `.query()` method matching the `pg` signature.
|
|
8
|
+
*/
|
|
9
|
+
export interface DatabaseClient {
|
|
10
|
+
query(
|
|
11
|
+
text: string,
|
|
12
|
+
values?: any[],
|
|
13
|
+
): Promise<{ rows: any[]; rowCount: number | null }>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Options for `addJob()` beyond the job itself.
|
|
18
|
+
* Use `db` to insert the job within an existing database transaction.
|
|
19
|
+
*/
|
|
20
|
+
export interface AddJobOptions {
|
|
21
|
+
/**
|
|
22
|
+
* An external database client (e.g., a `pg.PoolClient` inside a transaction).
|
|
23
|
+
* When provided, the INSERT runs on this client instead of the internal pool,
|
|
24
|
+
* so the job is part of the caller's transaction.
|
|
25
|
+
*
|
|
26
|
+
* **PostgreSQL only.** Throws if used with the Redis backend.
|
|
27
|
+
*/
|
|
28
|
+
db?: DatabaseClient;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Optional grouping metadata for a job.
|
|
33
|
+
* Use `id` to enforce global per-group concurrency limits when
|
|
34
|
+
* `ProcessorOptions.groupConcurrency` is set.
|
|
35
|
+
*
|
|
36
|
+
* `tier` is reserved for future tier-based policies.
|
|
37
|
+
*/
|
|
38
|
+
export interface JobGroup {
|
|
39
|
+
/** Stable group identifier (for example: tenant ID, user ID, organization ID). */
|
|
40
|
+
id: string;
|
|
41
|
+
/** Optional tier label reserved for future tier-based concurrency controls. */
|
|
42
|
+
tier?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
4
45
|
export interface JobOptions<PayloadMap, T extends JobType<PayloadMap>> {
|
|
5
46
|
jobType: T;
|
|
6
47
|
payload: PayloadMap[T];
|
|
@@ -73,6 +114,32 @@ export interface JobOptions<PayloadMap, T extends JobType<PayloadMap>> {
|
|
|
73
114
|
* Once a key exists, it cannot be reused until the job is cleaned up (via `cleanupOldJobs`).
|
|
74
115
|
*/
|
|
75
116
|
idempotencyKey?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Base delay between retries in seconds. When `retryBackoff` is true (the default),
|
|
119
|
+
* this is the base for exponential backoff: `retryDelay * 2^attempts`.
|
|
120
|
+
* When `retryBackoff` is false, retries use this fixed delay.
|
|
121
|
+
* @default 60
|
|
122
|
+
*/
|
|
123
|
+
retryDelay?: number;
|
|
124
|
+
/**
|
|
125
|
+
* Whether to use exponential backoff for retries. When true, delay doubles
|
|
126
|
+
* with each attempt and includes jitter to prevent thundering herd.
|
|
127
|
+
* When false, a fixed `retryDelay` is used between every retry.
|
|
128
|
+
* @default true
|
|
129
|
+
*/
|
|
130
|
+
retryBackoff?: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Maximum delay between retries in seconds. Caps the exponential backoff
|
|
133
|
+
* so retries never wait longer than this value. Only meaningful when
|
|
134
|
+
* `retryBackoff` is true. No limit when omitted.
|
|
135
|
+
*/
|
|
136
|
+
retryDelayMax?: number;
|
|
137
|
+
/**
|
|
138
|
+
* Optional group metadata for this job.
|
|
139
|
+
* When `ProcessorOptions.groupConcurrency` is configured, grouped jobs are
|
|
140
|
+
* globally limited by `group.id` across all workers/instances.
|
|
141
|
+
*/
|
|
142
|
+
group?: JobGroup;
|
|
76
143
|
}
|
|
77
144
|
|
|
78
145
|
/**
|
|
@@ -196,6 +263,31 @@ export interface JobRecord<PayloadMap, T extends JobType<PayloadMap>> {
|
|
|
196
263
|
* Updated by the handler via `ctx.setProgress(percent)`.
|
|
197
264
|
*/
|
|
198
265
|
progress?: number | null;
|
|
266
|
+
/**
|
|
267
|
+
* Handler output stored via `ctx.setOutput(data)` or by returning a value
|
|
268
|
+
* from the handler. `null` if no output has been stored.
|
|
269
|
+
*/
|
|
270
|
+
output?: unknown;
|
|
271
|
+
/**
|
|
272
|
+
* Base delay between retries in seconds, or null if using legacy default.
|
|
273
|
+
*/
|
|
274
|
+
retryDelay?: number | null;
|
|
275
|
+
/**
|
|
276
|
+
* Whether exponential backoff is enabled for retries, or null if using legacy default.
|
|
277
|
+
*/
|
|
278
|
+
retryBackoff?: boolean | null;
|
|
279
|
+
/**
|
|
280
|
+
* Maximum delay cap for retries in seconds, or null if no cap.
|
|
281
|
+
*/
|
|
282
|
+
retryDelayMax?: number | null;
|
|
283
|
+
/**
|
|
284
|
+
* Group identifier for this job, if provided at enqueue time.
|
|
285
|
+
*/
|
|
286
|
+
groupId?: string | null;
|
|
287
|
+
/**
|
|
288
|
+
* Group tier for this job, if provided at enqueue time.
|
|
289
|
+
*/
|
|
290
|
+
groupTier?: string | null;
|
|
199
291
|
}
|
|
200
292
|
|
|
201
293
|
/**
|
|
@@ -292,6 +384,17 @@ export interface JobContext {
|
|
|
292
384
|
* @throws If percent is outside the 0-100 range.
|
|
293
385
|
*/
|
|
294
386
|
setProgress: (percent: number) => Promise<void>;
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Store an output/result for this job. The value is persisted to the database
|
|
390
|
+
* as JSONB and can be read by clients via `getJob()` or the React SDK's `useJob()` hook.
|
|
391
|
+
*
|
|
392
|
+
* Can be called multiple times — each call overwrites the previous value.
|
|
393
|
+
* If `setOutput()` is called, the handler's return value is ignored.
|
|
394
|
+
*
|
|
395
|
+
* @param data - Any JSON-serializable value to store as the job's output.
|
|
396
|
+
*/
|
|
397
|
+
setOutput: (data: unknown) => Promise<void>;
|
|
295
398
|
}
|
|
296
399
|
|
|
297
400
|
/**
|
|
@@ -380,7 +483,7 @@ export type JobHandler<PayloadMap, T extends keyof PayloadMap> = (
|
|
|
380
483
|
payload: PayloadMap[T],
|
|
381
484
|
signal: AbortSignal,
|
|
382
485
|
ctx: JobContext,
|
|
383
|
-
) => Promise<
|
|
486
|
+
) => Promise<unknown>;
|
|
384
487
|
|
|
385
488
|
export type JobHandlers<PayloadMap> = {
|
|
386
489
|
[K in keyof PayloadMap]: JobHandler<PayloadMap, K>;
|
|
@@ -401,6 +504,13 @@ export interface ProcessorOptions {
|
|
|
401
504
|
* - Set to a lower value to avoid resource exhaustion.
|
|
402
505
|
*/
|
|
403
506
|
concurrency?: number;
|
|
507
|
+
/**
|
|
508
|
+
* Global per-group concurrency limit across all workers/instances.
|
|
509
|
+
* - Applies only to jobs with `group.id` set.
|
|
510
|
+
* - Jobs without a group are unaffected.
|
|
511
|
+
* - Disabled when omitted.
|
|
512
|
+
*/
|
|
513
|
+
groupConcurrency?: number;
|
|
404
514
|
/**
|
|
405
515
|
* The interval in milliseconds to poll for new jobs.
|
|
406
516
|
* - If not provided, the processor will process jobs every 5 seconds when startInBackground is called.
|
|
@@ -452,6 +562,91 @@ export interface Processor {
|
|
|
452
562
|
start: () => Promise<number>;
|
|
453
563
|
}
|
|
454
564
|
|
|
565
|
+
export interface SupervisorOptions {
|
|
566
|
+
/**
|
|
567
|
+
* How often the maintenance loop runs, in milliseconds.
|
|
568
|
+
* @default 60000 (1 minute)
|
|
569
|
+
*/
|
|
570
|
+
intervalMs?: number;
|
|
571
|
+
/**
|
|
572
|
+
* Reclaim jobs stuck in `processing` longer than this many minutes.
|
|
573
|
+
* @default 10
|
|
574
|
+
*/
|
|
575
|
+
stuckJobsTimeoutMinutes?: number;
|
|
576
|
+
/**
|
|
577
|
+
* Auto-delete completed jobs older than this many days. Set to 0 to disable.
|
|
578
|
+
* @default 30
|
|
579
|
+
*/
|
|
580
|
+
cleanupJobsDaysToKeep?: number;
|
|
581
|
+
/**
|
|
582
|
+
* Auto-delete job events older than this many days. Set to 0 to disable.
|
|
583
|
+
* @default 30
|
|
584
|
+
*/
|
|
585
|
+
cleanupEventsDaysToKeep?: number;
|
|
586
|
+
/**
|
|
587
|
+
* Batch size for cleanup deletions.
|
|
588
|
+
* @default 1000
|
|
589
|
+
*/
|
|
590
|
+
cleanupBatchSize?: number;
|
|
591
|
+
/**
|
|
592
|
+
* Whether to reclaim stuck jobs each cycle.
|
|
593
|
+
* @default true
|
|
594
|
+
*/
|
|
595
|
+
reclaimStuckJobs?: boolean;
|
|
596
|
+
/**
|
|
597
|
+
* Whether to expire timed-out waitpoint tokens each cycle.
|
|
598
|
+
* @default true
|
|
599
|
+
*/
|
|
600
|
+
expireTimedOutTokens?: boolean;
|
|
601
|
+
/**
|
|
602
|
+
* Called when a maintenance task throws. One failure does not block other tasks.
|
|
603
|
+
* @default console.error
|
|
604
|
+
*/
|
|
605
|
+
onError?: (error: Error) => void;
|
|
606
|
+
/** Enable verbose logging. */
|
|
607
|
+
verbose?: boolean;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
export interface SupervisorRunResult {
|
|
611
|
+
/** Number of stuck jobs reclaimed back to pending. */
|
|
612
|
+
reclaimedJobs: number;
|
|
613
|
+
/** Number of old completed jobs deleted. */
|
|
614
|
+
cleanedUpJobs: number;
|
|
615
|
+
/** Number of old job events deleted. */
|
|
616
|
+
cleanedUpEvents: number;
|
|
617
|
+
/** Number of timed-out waitpoint tokens expired. */
|
|
618
|
+
expiredTokens: number;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
export interface Supervisor {
|
|
622
|
+
/**
|
|
623
|
+
* Run all maintenance tasks once and return the results.
|
|
624
|
+
* Ideal for serverless or cron-triggered invocations.
|
|
625
|
+
*/
|
|
626
|
+
start: () => Promise<SupervisorRunResult>;
|
|
627
|
+
/**
|
|
628
|
+
* Start the maintenance loop in the background.
|
|
629
|
+
* Runs every `intervalMs` milliseconds (default: 60 000).
|
|
630
|
+
* Call `stop()` or `stopAndDrain()` to halt the loop.
|
|
631
|
+
*/
|
|
632
|
+
startInBackground: () => void;
|
|
633
|
+
/**
|
|
634
|
+
* Stop the background maintenance loop immediately.
|
|
635
|
+
* Does not wait for an in-flight maintenance run to complete.
|
|
636
|
+
*/
|
|
637
|
+
stop: () => void;
|
|
638
|
+
/**
|
|
639
|
+
* Stop the background loop and wait for the current maintenance run
|
|
640
|
+
* (if any) to finish before resolving.
|
|
641
|
+
*
|
|
642
|
+
* @param timeoutMs - Maximum time to wait (default: 30 000 ms).
|
|
643
|
+
* If the run does not finish within this time the promise resolves anyway.
|
|
644
|
+
*/
|
|
645
|
+
stopAndDrain: (timeoutMs?: number) => Promise<void>;
|
|
646
|
+
/** Whether the background maintenance loop is currently running. */
|
|
647
|
+
isRunning: () => boolean;
|
|
648
|
+
}
|
|
649
|
+
|
|
455
650
|
export interface DatabaseSSLConfig {
|
|
456
651
|
/**
|
|
457
652
|
* CA certificate as PEM string or file path. If the value starts with 'file://', it will be loaded from file, otherwise treated as PEM string.
|
|
@@ -474,10 +669,13 @@ export interface DatabaseSSLConfig {
|
|
|
474
669
|
/**
|
|
475
670
|
* Configuration for PostgreSQL backend (default).
|
|
476
671
|
* Backward-compatible: omitting `backend` defaults to 'postgres'.
|
|
672
|
+
*
|
|
673
|
+
* Provide either `databaseConfig` (the library creates a pool) or `pool`
|
|
674
|
+
* (bring your own `pg.Pool`). At least one must be set.
|
|
477
675
|
*/
|
|
478
676
|
export interface PostgresJobQueueConfig {
|
|
479
677
|
backend?: 'postgres';
|
|
480
|
-
databaseConfig
|
|
678
|
+
databaseConfig?: {
|
|
481
679
|
connectionString?: string;
|
|
482
680
|
host?: string;
|
|
483
681
|
port?: number;
|
|
@@ -503,6 +701,11 @@ export interface PostgresJobQueueConfig {
|
|
|
503
701
|
*/
|
|
504
702
|
connectionTimeoutMillis?: number;
|
|
505
703
|
};
|
|
704
|
+
/**
|
|
705
|
+
* Bring your own `pg.Pool` instance. When provided, `databaseConfig` is
|
|
706
|
+
* ignored and the library will not close the pool on shutdown.
|
|
707
|
+
*/
|
|
708
|
+
pool?: import('pg').Pool;
|
|
506
709
|
verbose?: boolean;
|
|
507
710
|
}
|
|
508
711
|
|
|
@@ -518,10 +721,13 @@ export interface RedisTLSConfig {
|
|
|
518
721
|
|
|
519
722
|
/**
|
|
520
723
|
* Configuration for Redis backend.
|
|
724
|
+
*
|
|
725
|
+
* Provide either `redisConfig` (the library creates an ioredis client) or
|
|
726
|
+
* `client` (bring your own ioredis instance). At least one must be set.
|
|
521
727
|
*/
|
|
522
728
|
export interface RedisJobQueueConfig {
|
|
523
729
|
backend: 'redis';
|
|
524
|
-
redisConfig
|
|
730
|
+
redisConfig?: {
|
|
525
731
|
/** Redis URL (e.g. redis://localhost:6379) */
|
|
526
732
|
url?: string;
|
|
527
733
|
host?: string;
|
|
@@ -536,6 +742,17 @@ export interface RedisJobQueueConfig {
|
|
|
536
742
|
*/
|
|
537
743
|
keyPrefix?: string;
|
|
538
744
|
};
|
|
745
|
+
/**
|
|
746
|
+
* Bring your own ioredis client instance. When provided, `redisConfig` is
|
|
747
|
+
* ignored and the library will not close the client on shutdown.
|
|
748
|
+
* Use `keyPrefix` to set the key namespace (default: 'dq:').
|
|
749
|
+
*/
|
|
750
|
+
client?: unknown;
|
|
751
|
+
/**
|
|
752
|
+
* Key prefix when using an external `client`. Ignored when `redisConfig` is used
|
|
753
|
+
* (set `redisConfig.keyPrefix` instead). Default: 'dq:'.
|
|
754
|
+
*/
|
|
755
|
+
keyPrefix?: string;
|
|
539
756
|
verbose?: boolean;
|
|
540
757
|
}
|
|
541
758
|
|
|
@@ -592,6 +809,12 @@ export interface CronScheduleOptions<
|
|
|
592
809
|
* is still pending, processing, or waiting.
|
|
593
810
|
*/
|
|
594
811
|
allowOverlap?: boolean;
|
|
812
|
+
/** Base delay between retries in seconds for each job instance (default: 60). */
|
|
813
|
+
retryDelay?: number;
|
|
814
|
+
/** Whether to use exponential backoff for retries (default: true). */
|
|
815
|
+
retryBackoff?: boolean;
|
|
816
|
+
/** Maximum delay cap for retries in seconds. */
|
|
817
|
+
retryDelayMax?: number;
|
|
595
818
|
}
|
|
596
819
|
|
|
597
820
|
/**
|
|
@@ -616,6 +839,9 @@ export interface CronScheduleRecord {
|
|
|
616
839
|
nextRunAt: Date | null;
|
|
617
840
|
createdAt: Date;
|
|
618
841
|
updatedAt: Date;
|
|
842
|
+
retryDelay: number | null;
|
|
843
|
+
retryBackoff: boolean | null;
|
|
844
|
+
retryDelayMax: number | null;
|
|
619
845
|
}
|
|
620
846
|
|
|
621
847
|
/**
|
|
@@ -632,15 +858,87 @@ export interface EditCronScheduleOptions {
|
|
|
632
858
|
tags?: string[] | null;
|
|
633
859
|
timezone?: string;
|
|
634
860
|
allowOverlap?: boolean;
|
|
861
|
+
retryDelay?: number | null;
|
|
862
|
+
retryBackoff?: boolean | null;
|
|
863
|
+
retryDelayMax?: number | null;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// ── Event hooks ──────────────────────────────────────────────────────
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* Payload types for each event emitted by the job queue.
|
|
870
|
+
*/
|
|
871
|
+
export interface QueueEventMap {
|
|
872
|
+
/** Fired after a job is successfully added to the queue. */
|
|
873
|
+
'job:added': { jobId: number; jobType: string };
|
|
874
|
+
/** Fired when a processor claims a job and begins executing its handler. */
|
|
875
|
+
'job:processing': { jobId: number; jobType: string };
|
|
876
|
+
/** Fired when a job handler completes successfully. */
|
|
877
|
+
'job:completed': { jobId: number; jobType: string };
|
|
878
|
+
/** Fired when a job handler fails. `willRetry` indicates whether the job will be retried. */
|
|
879
|
+
'job:failed': {
|
|
880
|
+
jobId: number;
|
|
881
|
+
jobType: string;
|
|
882
|
+
error: Error;
|
|
883
|
+
willRetry: boolean;
|
|
884
|
+
};
|
|
885
|
+
/** Fired after a job is cancelled via `cancelJob()`. */
|
|
886
|
+
'job:cancelled': { jobId: number };
|
|
887
|
+
/** Fired after a failed job is manually retried via `retryJob()`. */
|
|
888
|
+
'job:retried': { jobId: number };
|
|
889
|
+
/** Fired when a job enters the `waiting` state (via `ctx.waitFor`, `ctx.waitUntil`, or `ctx.waitForToken`). */
|
|
890
|
+
'job:waiting': { jobId: number; jobType: string };
|
|
891
|
+
/** Fired when a job reports progress via `ctx.setProgress()`. */
|
|
892
|
+
'job:progress': { jobId: number; progress: number };
|
|
893
|
+
/** Fired when a job stores output via `ctx.setOutput()`. */
|
|
894
|
+
'job:output': { jobId: number; output: unknown };
|
|
895
|
+
/** Fired on internal errors from the processor or supervisor. */
|
|
896
|
+
error: Error;
|
|
635
897
|
}
|
|
636
898
|
|
|
899
|
+
/** Union of all event names supported by the job queue. */
|
|
900
|
+
export type QueueEventName = keyof QueueEventMap;
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* Callback type for `emit`. Used internally to pass the emitter
|
|
904
|
+
* from `initJobQueue` into the processor and supervisor.
|
|
905
|
+
*/
|
|
906
|
+
export type QueueEmitFn = <K extends QueueEventName>(
|
|
907
|
+
event: K,
|
|
908
|
+
data: QueueEventMap[K],
|
|
909
|
+
) => void;
|
|
910
|
+
|
|
637
911
|
export interface JobQueue<PayloadMap> {
|
|
638
912
|
/**
|
|
639
913
|
* Add a job to the job queue.
|
|
914
|
+
*
|
|
915
|
+
* @param job - The job to enqueue.
|
|
916
|
+
* @param options - Optional. Pass `{ db }` with an external database client
|
|
917
|
+
* to insert the job within an existing transaction (PostgreSQL only).
|
|
640
918
|
*/
|
|
641
919
|
addJob: <T extends JobType<PayloadMap>>(
|
|
642
920
|
job: JobOptions<PayloadMap, T>,
|
|
921
|
+
options?: AddJobOptions,
|
|
643
922
|
) => Promise<number>;
|
|
923
|
+
/**
|
|
924
|
+
* Add multiple jobs to the queue in a single operation.
|
|
925
|
+
*
|
|
926
|
+
* More efficient than calling `addJob` in a loop because it batches the
|
|
927
|
+
* INSERT into a single database round-trip (PostgreSQL) or a single
|
|
928
|
+
* atomic Lua script (Redis).
|
|
929
|
+
*
|
|
930
|
+
* Returns an array of job IDs in the same order as the input array.
|
|
931
|
+
* Each job may independently have an `idempotencyKey`; duplicates
|
|
932
|
+
* resolve to the existing job's ID without creating a new row.
|
|
933
|
+
*
|
|
934
|
+
* @param jobs - Array of jobs to enqueue.
|
|
935
|
+
* @param options - Optional. Pass `{ db }` with an external database client
|
|
936
|
+
* to insert the jobs within an existing transaction (PostgreSQL only).
|
|
937
|
+
*/
|
|
938
|
+
addJobs: <T extends JobType<PayloadMap>>(
|
|
939
|
+
jobs: JobOptions<PayloadMap, T>[],
|
|
940
|
+
options?: AddJobOptions,
|
|
941
|
+
) => Promise<number[]>;
|
|
644
942
|
/**
|
|
645
943
|
* Get a job by its ID.
|
|
646
944
|
*/
|
|
@@ -795,6 +1093,13 @@ export interface JobQueue<PayloadMap> {
|
|
|
795
1093
|
options?: ProcessorOptions,
|
|
796
1094
|
) => Processor;
|
|
797
1095
|
|
|
1096
|
+
/**
|
|
1097
|
+
* Create a background supervisor that automatically reclaims stuck jobs,
|
|
1098
|
+
* cleans up old completed jobs/events, and expires timed-out waitpoint
|
|
1099
|
+
* tokens on a configurable interval.
|
|
1100
|
+
*/
|
|
1101
|
+
createSupervisor: (options?: SupervisorOptions) => Supervisor;
|
|
1102
|
+
|
|
798
1103
|
/**
|
|
799
1104
|
* Get the job events for a job.
|
|
800
1105
|
*/
|
|
@@ -898,6 +1203,51 @@ export interface JobQueue<PayloadMap> {
|
|
|
898
1203
|
*/
|
|
899
1204
|
enqueueDueCronJobs: () => Promise<number>;
|
|
900
1205
|
|
|
1206
|
+
// ── Event hooks ───────────────────────────────────────────────────────
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Register a listener for a queue event. The listener is called every
|
|
1210
|
+
* time the event fires. Works identically with both PostgreSQL and Redis.
|
|
1211
|
+
*
|
|
1212
|
+
* @param event - The event name (e.g. `'job:completed'`, `'error'`).
|
|
1213
|
+
* @param listener - Callback receiving the event payload.
|
|
1214
|
+
*/
|
|
1215
|
+
on: <K extends QueueEventName>(
|
|
1216
|
+
event: K,
|
|
1217
|
+
listener: (data: QueueEventMap[K]) => void,
|
|
1218
|
+
) => void;
|
|
1219
|
+
|
|
1220
|
+
/**
|
|
1221
|
+
* Register a one-time listener. The listener is automatically removed
|
|
1222
|
+
* after it fires once.
|
|
1223
|
+
*
|
|
1224
|
+
* @param event - The event name.
|
|
1225
|
+
* @param listener - Callback receiving the event payload.
|
|
1226
|
+
*/
|
|
1227
|
+
once: <K extends QueueEventName>(
|
|
1228
|
+
event: K,
|
|
1229
|
+
listener: (data: QueueEventMap[K]) => void,
|
|
1230
|
+
) => void;
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* Remove a previously registered listener.
|
|
1234
|
+
*
|
|
1235
|
+
* @param event - The event name.
|
|
1236
|
+
* @param listener - The exact function reference passed to `on` or `once`.
|
|
1237
|
+
*/
|
|
1238
|
+
off: <K extends QueueEventName>(
|
|
1239
|
+
event: K,
|
|
1240
|
+
listener: (data: QueueEventMap[K]) => void,
|
|
1241
|
+
) => void;
|
|
1242
|
+
|
|
1243
|
+
/**
|
|
1244
|
+
* Remove all listeners for a specific event, or all listeners for
|
|
1245
|
+
* all events when called without arguments.
|
|
1246
|
+
*
|
|
1247
|
+
* @param event - Optional event name. If omitted, removes everything.
|
|
1248
|
+
*/
|
|
1249
|
+
removeAllListeners: (event?: QueueEventName) => void;
|
|
1250
|
+
|
|
901
1251
|
// ── Advanced access ───────────────────────────────────────────────────
|
|
902
1252
|
|
|
903
1253
|
/**
|