@nicnocquee/dataqueue 1.34.0 → 1.35.0-beta.20260224075710
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 +23 -11
- package/ai/rules/advanced.md +77 -1
- package/ai/rules/basic.md +72 -3
- package/ai/rules/react-dashboard.md +5 -1
- package/ai/skills/dataqueue-advanced/SKILL.md +159 -0
- package/ai/skills/dataqueue-core/SKILL.md +107 -3
- package/ai/skills/dataqueue-react/SKILL.md +19 -7
- package/dist/index.cjs +937 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +358 -11
- package/dist/index.d.ts +358 -11
- package/dist/index.js +937 -108
- 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/package.json +1 -1
- package/src/backend.ts +36 -3
- package/src/backends/postgres.ts +344 -42
- package/src/backends/redis-scripts.ts +173 -8
- package/src/backends/redis.test.ts +668 -0
- package/src/backends/redis.ts +244 -15
- package/src/db-util.ts +1 -1
- package/src/index.test.ts +811 -12
- package/src/index.ts +106 -14
- package/src/processor.ts +133 -49
- package/src/queue.test.ts +477 -0
- package/src/queue.ts +20 -3
- package/src/supervisor.test.ts +340 -0
- package/src/supervisor.ts +177 -0
- package/src/types.ts +318 -3
package/dist/index.d.cts
CHANGED
|
@@ -3,6 +3,31 @@ import { Pool } from 'pg';
|
|
|
3
3
|
import { Cron } from 'croner';
|
|
4
4
|
|
|
5
5
|
type JobType<PayloadMap> = keyof PayloadMap & string;
|
|
6
|
+
/**
|
|
7
|
+
* Abstract database client interface for transactional job creation.
|
|
8
|
+
* Compatible with `pg.Pool`, `pg.PoolClient`, `pg.Client`, or any object
|
|
9
|
+
* that exposes a `.query()` method matching the `pg` signature.
|
|
10
|
+
*/
|
|
11
|
+
interface DatabaseClient {
|
|
12
|
+
query(text: string, values?: any[]): Promise<{
|
|
13
|
+
rows: any[];
|
|
14
|
+
rowCount: number | null;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Options for `addJob()` beyond the job itself.
|
|
19
|
+
* Use `db` to insert the job within an existing database transaction.
|
|
20
|
+
*/
|
|
21
|
+
interface AddJobOptions {
|
|
22
|
+
/**
|
|
23
|
+
* An external database client (e.g., a `pg.PoolClient` inside a transaction).
|
|
24
|
+
* When provided, the INSERT runs on this client instead of the internal pool,
|
|
25
|
+
* so the job is part of the caller's transaction.
|
|
26
|
+
*
|
|
27
|
+
* **PostgreSQL only.** Throws if used with the Redis backend.
|
|
28
|
+
*/
|
|
29
|
+
db?: DatabaseClient;
|
|
30
|
+
}
|
|
6
31
|
interface JobOptions<PayloadMap, T extends JobType<PayloadMap>> {
|
|
7
32
|
jobType: T;
|
|
8
33
|
payload: PayloadMap[T];
|
|
@@ -75,6 +100,26 @@ interface JobOptions<PayloadMap, T extends JobType<PayloadMap>> {
|
|
|
75
100
|
* Once a key exists, it cannot be reused until the job is cleaned up (via `cleanupOldJobs`).
|
|
76
101
|
*/
|
|
77
102
|
idempotencyKey?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Base delay between retries in seconds. When `retryBackoff` is true (the default),
|
|
105
|
+
* this is the base for exponential backoff: `retryDelay * 2^attempts`.
|
|
106
|
+
* When `retryBackoff` is false, retries use this fixed delay.
|
|
107
|
+
* @default 60
|
|
108
|
+
*/
|
|
109
|
+
retryDelay?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Whether to use exponential backoff for retries. When true, delay doubles
|
|
112
|
+
* with each attempt and includes jitter to prevent thundering herd.
|
|
113
|
+
* When false, a fixed `retryDelay` is used between every retry.
|
|
114
|
+
* @default true
|
|
115
|
+
*/
|
|
116
|
+
retryBackoff?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Maximum delay between retries in seconds. Caps the exponential backoff
|
|
119
|
+
* so retries never wait longer than this value. Only meaningful when
|
|
120
|
+
* `retryBackoff` is true. No limit when omitted.
|
|
121
|
+
*/
|
|
122
|
+
retryDelayMax?: number;
|
|
78
123
|
}
|
|
79
124
|
/**
|
|
80
125
|
* Options for editing a pending job.
|
|
@@ -187,6 +232,23 @@ interface JobRecord<PayloadMap, T extends JobType<PayloadMap>> {
|
|
|
187
232
|
* Updated by the handler via `ctx.setProgress(percent)`.
|
|
188
233
|
*/
|
|
189
234
|
progress?: number | null;
|
|
235
|
+
/**
|
|
236
|
+
* Handler output stored via `ctx.setOutput(data)` or by returning a value
|
|
237
|
+
* from the handler. `null` if no output has been stored.
|
|
238
|
+
*/
|
|
239
|
+
output?: unknown;
|
|
240
|
+
/**
|
|
241
|
+
* Base delay between retries in seconds, or null if using legacy default.
|
|
242
|
+
*/
|
|
243
|
+
retryDelay?: number | null;
|
|
244
|
+
/**
|
|
245
|
+
* Whether exponential backoff is enabled for retries, or null if using legacy default.
|
|
246
|
+
*/
|
|
247
|
+
retryBackoff?: boolean | null;
|
|
248
|
+
/**
|
|
249
|
+
* Maximum delay cap for retries in seconds, or null if no cap.
|
|
250
|
+
*/
|
|
251
|
+
retryDelayMax?: number | null;
|
|
190
252
|
}
|
|
191
253
|
/**
|
|
192
254
|
* Callback registered via `onTimeout`. Invoked when the timeout fires, before the AbortSignal is triggered.
|
|
@@ -274,6 +336,16 @@ interface JobContext {
|
|
|
274
336
|
* @throws If percent is outside the 0-100 range.
|
|
275
337
|
*/
|
|
276
338
|
setProgress: (percent: number) => Promise<void>;
|
|
339
|
+
/**
|
|
340
|
+
* Store an output/result for this job. The value is persisted to the database
|
|
341
|
+
* as JSONB and can be read by clients via `getJob()` or the React SDK's `useJob()` hook.
|
|
342
|
+
*
|
|
343
|
+
* Can be called multiple times — each call overwrites the previous value.
|
|
344
|
+
* If `setOutput()` is called, the handler's return value is ignored.
|
|
345
|
+
*
|
|
346
|
+
* @param data - Any JSON-serializable value to store as the job's output.
|
|
347
|
+
*/
|
|
348
|
+
setOutput: (data: unknown) => Promise<void>;
|
|
277
349
|
}
|
|
278
350
|
/**
|
|
279
351
|
* Duration specification for `ctx.waitFor()`.
|
|
@@ -349,7 +421,7 @@ interface WaitpointRecord {
|
|
|
349
421
|
completedAt: Date | null;
|
|
350
422
|
tags: string[] | null;
|
|
351
423
|
}
|
|
352
|
-
type JobHandler<PayloadMap, T extends keyof PayloadMap> = (payload: PayloadMap[T], signal: AbortSignal, ctx: JobContext) => Promise<
|
|
424
|
+
type JobHandler<PayloadMap, T extends keyof PayloadMap> = (payload: PayloadMap[T], signal: AbortSignal, ctx: JobContext) => Promise<unknown>;
|
|
353
425
|
type JobHandlers<PayloadMap> = {
|
|
354
426
|
[K in keyof PayloadMap]: JobHandler<PayloadMap, K>;
|
|
355
427
|
};
|
|
@@ -417,6 +489,88 @@ interface Processor {
|
|
|
417
489
|
*/
|
|
418
490
|
start: () => Promise<number>;
|
|
419
491
|
}
|
|
492
|
+
interface SupervisorOptions {
|
|
493
|
+
/**
|
|
494
|
+
* How often the maintenance loop runs, in milliseconds.
|
|
495
|
+
* @default 60000 (1 minute)
|
|
496
|
+
*/
|
|
497
|
+
intervalMs?: number;
|
|
498
|
+
/**
|
|
499
|
+
* Reclaim jobs stuck in `processing` longer than this many minutes.
|
|
500
|
+
* @default 10
|
|
501
|
+
*/
|
|
502
|
+
stuckJobsTimeoutMinutes?: number;
|
|
503
|
+
/**
|
|
504
|
+
* Auto-delete completed jobs older than this many days. Set to 0 to disable.
|
|
505
|
+
* @default 30
|
|
506
|
+
*/
|
|
507
|
+
cleanupJobsDaysToKeep?: number;
|
|
508
|
+
/**
|
|
509
|
+
* Auto-delete job events older than this many days. Set to 0 to disable.
|
|
510
|
+
* @default 30
|
|
511
|
+
*/
|
|
512
|
+
cleanupEventsDaysToKeep?: number;
|
|
513
|
+
/**
|
|
514
|
+
* Batch size for cleanup deletions.
|
|
515
|
+
* @default 1000
|
|
516
|
+
*/
|
|
517
|
+
cleanupBatchSize?: number;
|
|
518
|
+
/**
|
|
519
|
+
* Whether to reclaim stuck jobs each cycle.
|
|
520
|
+
* @default true
|
|
521
|
+
*/
|
|
522
|
+
reclaimStuckJobs?: boolean;
|
|
523
|
+
/**
|
|
524
|
+
* Whether to expire timed-out waitpoint tokens each cycle.
|
|
525
|
+
* @default true
|
|
526
|
+
*/
|
|
527
|
+
expireTimedOutTokens?: boolean;
|
|
528
|
+
/**
|
|
529
|
+
* Called when a maintenance task throws. One failure does not block other tasks.
|
|
530
|
+
* @default console.error
|
|
531
|
+
*/
|
|
532
|
+
onError?: (error: Error) => void;
|
|
533
|
+
/** Enable verbose logging. */
|
|
534
|
+
verbose?: boolean;
|
|
535
|
+
}
|
|
536
|
+
interface SupervisorRunResult {
|
|
537
|
+
/** Number of stuck jobs reclaimed back to pending. */
|
|
538
|
+
reclaimedJobs: number;
|
|
539
|
+
/** Number of old completed jobs deleted. */
|
|
540
|
+
cleanedUpJobs: number;
|
|
541
|
+
/** Number of old job events deleted. */
|
|
542
|
+
cleanedUpEvents: number;
|
|
543
|
+
/** Number of timed-out waitpoint tokens expired. */
|
|
544
|
+
expiredTokens: number;
|
|
545
|
+
}
|
|
546
|
+
interface Supervisor {
|
|
547
|
+
/**
|
|
548
|
+
* Run all maintenance tasks once and return the results.
|
|
549
|
+
* Ideal for serverless or cron-triggered invocations.
|
|
550
|
+
*/
|
|
551
|
+
start: () => Promise<SupervisorRunResult>;
|
|
552
|
+
/**
|
|
553
|
+
* Start the maintenance loop in the background.
|
|
554
|
+
* Runs every `intervalMs` milliseconds (default: 60 000).
|
|
555
|
+
* Call `stop()` or `stopAndDrain()` to halt the loop.
|
|
556
|
+
*/
|
|
557
|
+
startInBackground: () => void;
|
|
558
|
+
/**
|
|
559
|
+
* Stop the background maintenance loop immediately.
|
|
560
|
+
* Does not wait for an in-flight maintenance run to complete.
|
|
561
|
+
*/
|
|
562
|
+
stop: () => void;
|
|
563
|
+
/**
|
|
564
|
+
* Stop the background loop and wait for the current maintenance run
|
|
565
|
+
* (if any) to finish before resolving.
|
|
566
|
+
*
|
|
567
|
+
* @param timeoutMs - Maximum time to wait (default: 30 000 ms).
|
|
568
|
+
* If the run does not finish within this time the promise resolves anyway.
|
|
569
|
+
*/
|
|
570
|
+
stopAndDrain: (timeoutMs?: number) => Promise<void>;
|
|
571
|
+
/** Whether the background maintenance loop is currently running. */
|
|
572
|
+
isRunning: () => boolean;
|
|
573
|
+
}
|
|
420
574
|
interface DatabaseSSLConfig {
|
|
421
575
|
/**
|
|
422
576
|
* 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.
|
|
@@ -438,10 +592,13 @@ interface DatabaseSSLConfig {
|
|
|
438
592
|
/**
|
|
439
593
|
* Configuration for PostgreSQL backend (default).
|
|
440
594
|
* Backward-compatible: omitting `backend` defaults to 'postgres'.
|
|
595
|
+
*
|
|
596
|
+
* Provide either `databaseConfig` (the library creates a pool) or `pool`
|
|
597
|
+
* (bring your own `pg.Pool`). At least one must be set.
|
|
441
598
|
*/
|
|
442
599
|
interface PostgresJobQueueConfig {
|
|
443
600
|
backend?: 'postgres';
|
|
444
|
-
databaseConfig
|
|
601
|
+
databaseConfig?: {
|
|
445
602
|
connectionString?: string;
|
|
446
603
|
host?: string;
|
|
447
604
|
port?: number;
|
|
@@ -467,6 +624,11 @@ interface PostgresJobQueueConfig {
|
|
|
467
624
|
*/
|
|
468
625
|
connectionTimeoutMillis?: number;
|
|
469
626
|
};
|
|
627
|
+
/**
|
|
628
|
+
* Bring your own `pg.Pool` instance. When provided, `databaseConfig` is
|
|
629
|
+
* ignored and the library will not close the pool on shutdown.
|
|
630
|
+
*/
|
|
631
|
+
pool?: pg.Pool;
|
|
470
632
|
verbose?: boolean;
|
|
471
633
|
}
|
|
472
634
|
/**
|
|
@@ -480,10 +642,13 @@ interface RedisTLSConfig {
|
|
|
480
642
|
}
|
|
481
643
|
/**
|
|
482
644
|
* Configuration for Redis backend.
|
|
645
|
+
*
|
|
646
|
+
* Provide either `redisConfig` (the library creates an ioredis client) or
|
|
647
|
+
* `client` (bring your own ioredis instance). At least one must be set.
|
|
483
648
|
*/
|
|
484
649
|
interface RedisJobQueueConfig {
|
|
485
650
|
backend: 'redis';
|
|
486
|
-
redisConfig
|
|
651
|
+
redisConfig?: {
|
|
487
652
|
/** Redis URL (e.g. redis://localhost:6379) */
|
|
488
653
|
url?: string;
|
|
489
654
|
host?: string;
|
|
@@ -498,6 +663,17 @@ interface RedisJobQueueConfig {
|
|
|
498
663
|
*/
|
|
499
664
|
keyPrefix?: string;
|
|
500
665
|
};
|
|
666
|
+
/**
|
|
667
|
+
* Bring your own ioredis client instance. When provided, `redisConfig` is
|
|
668
|
+
* ignored and the library will not close the client on shutdown.
|
|
669
|
+
* Use `keyPrefix` to set the key namespace (default: 'dq:').
|
|
670
|
+
*/
|
|
671
|
+
client?: unknown;
|
|
672
|
+
/**
|
|
673
|
+
* Key prefix when using an external `client`. Ignored when `redisConfig` is used
|
|
674
|
+
* (set `redisConfig.keyPrefix` instead). Default: 'dq:'.
|
|
675
|
+
*/
|
|
676
|
+
keyPrefix?: string;
|
|
501
677
|
verbose?: boolean;
|
|
502
678
|
}
|
|
503
679
|
/**
|
|
@@ -544,6 +720,12 @@ interface CronScheduleOptions<PayloadMap, T extends JobType<PayloadMap>> {
|
|
|
544
720
|
* is still pending, processing, or waiting.
|
|
545
721
|
*/
|
|
546
722
|
allowOverlap?: boolean;
|
|
723
|
+
/** Base delay between retries in seconds for each job instance (default: 60). */
|
|
724
|
+
retryDelay?: number;
|
|
725
|
+
/** Whether to use exponential backoff for retries (default: true). */
|
|
726
|
+
retryBackoff?: boolean;
|
|
727
|
+
/** Maximum delay cap for retries in seconds. */
|
|
728
|
+
retryDelayMax?: number;
|
|
547
729
|
}
|
|
548
730
|
/**
|
|
549
731
|
* A persisted cron schedule record.
|
|
@@ -567,6 +749,9 @@ interface CronScheduleRecord {
|
|
|
567
749
|
nextRunAt: Date | null;
|
|
568
750
|
createdAt: Date;
|
|
569
751
|
updatedAt: Date;
|
|
752
|
+
retryDelay: number | null;
|
|
753
|
+
retryBackoff: boolean | null;
|
|
754
|
+
retryDelayMax: number | null;
|
|
570
755
|
}
|
|
571
756
|
/**
|
|
572
757
|
* Options for editing an existing cron schedule.
|
|
@@ -582,12 +767,94 @@ interface EditCronScheduleOptions {
|
|
|
582
767
|
tags?: string[] | null;
|
|
583
768
|
timezone?: string;
|
|
584
769
|
allowOverlap?: boolean;
|
|
770
|
+
retryDelay?: number | null;
|
|
771
|
+
retryBackoff?: boolean | null;
|
|
772
|
+
retryDelayMax?: number | null;
|
|
585
773
|
}
|
|
774
|
+
/**
|
|
775
|
+
* Payload types for each event emitted by the job queue.
|
|
776
|
+
*/
|
|
777
|
+
interface QueueEventMap {
|
|
778
|
+
/** Fired after a job is successfully added to the queue. */
|
|
779
|
+
'job:added': {
|
|
780
|
+
jobId: number;
|
|
781
|
+
jobType: string;
|
|
782
|
+
};
|
|
783
|
+
/** Fired when a processor claims a job and begins executing its handler. */
|
|
784
|
+
'job:processing': {
|
|
785
|
+
jobId: number;
|
|
786
|
+
jobType: string;
|
|
787
|
+
};
|
|
788
|
+
/** Fired when a job handler completes successfully. */
|
|
789
|
+
'job:completed': {
|
|
790
|
+
jobId: number;
|
|
791
|
+
jobType: string;
|
|
792
|
+
};
|
|
793
|
+
/** Fired when a job handler fails. `willRetry` indicates whether the job will be retried. */
|
|
794
|
+
'job:failed': {
|
|
795
|
+
jobId: number;
|
|
796
|
+
jobType: string;
|
|
797
|
+
error: Error;
|
|
798
|
+
willRetry: boolean;
|
|
799
|
+
};
|
|
800
|
+
/** Fired after a job is cancelled via `cancelJob()`. */
|
|
801
|
+
'job:cancelled': {
|
|
802
|
+
jobId: number;
|
|
803
|
+
};
|
|
804
|
+
/** Fired after a failed job is manually retried via `retryJob()`. */
|
|
805
|
+
'job:retried': {
|
|
806
|
+
jobId: number;
|
|
807
|
+
};
|
|
808
|
+
/** Fired when a job enters the `waiting` state (via `ctx.waitFor`, `ctx.waitUntil`, or `ctx.waitForToken`). */
|
|
809
|
+
'job:waiting': {
|
|
810
|
+
jobId: number;
|
|
811
|
+
jobType: string;
|
|
812
|
+
};
|
|
813
|
+
/** Fired when a job reports progress via `ctx.setProgress()`. */
|
|
814
|
+
'job:progress': {
|
|
815
|
+
jobId: number;
|
|
816
|
+
progress: number;
|
|
817
|
+
};
|
|
818
|
+
/** Fired when a job stores output via `ctx.setOutput()`. */
|
|
819
|
+
'job:output': {
|
|
820
|
+
jobId: number;
|
|
821
|
+
output: unknown;
|
|
822
|
+
};
|
|
823
|
+
/** Fired on internal errors from the processor or supervisor. */
|
|
824
|
+
error: Error;
|
|
825
|
+
}
|
|
826
|
+
/** Union of all event names supported by the job queue. */
|
|
827
|
+
type QueueEventName = keyof QueueEventMap;
|
|
828
|
+
/**
|
|
829
|
+
* Callback type for `emit`. Used internally to pass the emitter
|
|
830
|
+
* from `initJobQueue` into the processor and supervisor.
|
|
831
|
+
*/
|
|
832
|
+
type QueueEmitFn = <K extends QueueEventName>(event: K, data: QueueEventMap[K]) => void;
|
|
586
833
|
interface JobQueue<PayloadMap> {
|
|
587
834
|
/**
|
|
588
835
|
* Add a job to the job queue.
|
|
836
|
+
*
|
|
837
|
+
* @param job - The job to enqueue.
|
|
838
|
+
* @param options - Optional. Pass `{ db }` with an external database client
|
|
839
|
+
* to insert the job within an existing transaction (PostgreSQL only).
|
|
840
|
+
*/
|
|
841
|
+
addJob: <T extends JobType<PayloadMap>>(job: JobOptions<PayloadMap, T>, options?: AddJobOptions) => Promise<number>;
|
|
842
|
+
/**
|
|
843
|
+
* Add multiple jobs to the queue in a single operation.
|
|
844
|
+
*
|
|
845
|
+
* More efficient than calling `addJob` in a loop because it batches the
|
|
846
|
+
* INSERT into a single database round-trip (PostgreSQL) or a single
|
|
847
|
+
* atomic Lua script (Redis).
|
|
848
|
+
*
|
|
849
|
+
* Returns an array of job IDs in the same order as the input array.
|
|
850
|
+
* Each job may independently have an `idempotencyKey`; duplicates
|
|
851
|
+
* resolve to the existing job's ID without creating a new row.
|
|
852
|
+
*
|
|
853
|
+
* @param jobs - Array of jobs to enqueue.
|
|
854
|
+
* @param options - Optional. Pass `{ db }` with an external database client
|
|
855
|
+
* to insert the jobs within an existing transaction (PostgreSQL only).
|
|
589
856
|
*/
|
|
590
|
-
|
|
857
|
+
addJobs: <T extends JobType<PayloadMap>>(jobs: JobOptions<PayloadMap, T>[], options?: AddJobOptions) => Promise<number[]>;
|
|
591
858
|
/**
|
|
592
859
|
* Get a job by its ID.
|
|
593
860
|
*/
|
|
@@ -732,6 +999,12 @@ interface JobQueue<PayloadMap> {
|
|
|
732
999
|
* Create a job processor. Handlers must be provided per-processor.
|
|
733
1000
|
*/
|
|
734
1001
|
createProcessor: (handlers: JobHandlers<PayloadMap>, options?: ProcessorOptions) => Processor;
|
|
1002
|
+
/**
|
|
1003
|
+
* Create a background supervisor that automatically reclaims stuck jobs,
|
|
1004
|
+
* cleans up old completed jobs/events, and expires timed-out waitpoint
|
|
1005
|
+
* tokens on a configurable interval.
|
|
1006
|
+
*/
|
|
1007
|
+
createSupervisor: (options?: SupervisorOptions) => Supervisor;
|
|
735
1008
|
/**
|
|
736
1009
|
* Get the job events for a job.
|
|
737
1010
|
*/
|
|
@@ -817,6 +1090,36 @@ interface JobQueue<PayloadMap> {
|
|
|
817
1090
|
* @returns The number of jobs that were enqueued.
|
|
818
1091
|
*/
|
|
819
1092
|
enqueueDueCronJobs: () => Promise<number>;
|
|
1093
|
+
/**
|
|
1094
|
+
* Register a listener for a queue event. The listener is called every
|
|
1095
|
+
* time the event fires. Works identically with both PostgreSQL and Redis.
|
|
1096
|
+
*
|
|
1097
|
+
* @param event - The event name (e.g. `'job:completed'`, `'error'`).
|
|
1098
|
+
* @param listener - Callback receiving the event payload.
|
|
1099
|
+
*/
|
|
1100
|
+
on: <K extends QueueEventName>(event: K, listener: (data: QueueEventMap[K]) => void) => void;
|
|
1101
|
+
/**
|
|
1102
|
+
* Register a one-time listener. The listener is automatically removed
|
|
1103
|
+
* after it fires once.
|
|
1104
|
+
*
|
|
1105
|
+
* @param event - The event name.
|
|
1106
|
+
* @param listener - Callback receiving the event payload.
|
|
1107
|
+
*/
|
|
1108
|
+
once: <K extends QueueEventName>(event: K, listener: (data: QueueEventMap[K]) => void) => void;
|
|
1109
|
+
/**
|
|
1110
|
+
* Remove a previously registered listener.
|
|
1111
|
+
*
|
|
1112
|
+
* @param event - The event name.
|
|
1113
|
+
* @param listener - The exact function reference passed to `on` or `once`.
|
|
1114
|
+
*/
|
|
1115
|
+
off: <K extends QueueEventName>(event: K, listener: (data: QueueEventMap[K]) => void) => void;
|
|
1116
|
+
/**
|
|
1117
|
+
* Remove all listeners for a specific event, or all listeners for
|
|
1118
|
+
* all events when called without arguments.
|
|
1119
|
+
*
|
|
1120
|
+
* @param event - Optional event name. If omitted, removes everything.
|
|
1121
|
+
*/
|
|
1122
|
+
removeAllListeners: (event?: QueueEventName) => void;
|
|
820
1123
|
/**
|
|
821
1124
|
* Get the PostgreSQL database pool.
|
|
822
1125
|
* Throws if the backend is not PostgreSQL.
|
|
@@ -863,6 +1166,9 @@ interface JobUpdates {
|
|
|
863
1166
|
runAt?: Date | null;
|
|
864
1167
|
timeoutMs?: number | null;
|
|
865
1168
|
tags?: string[] | null;
|
|
1169
|
+
retryDelay?: number | null;
|
|
1170
|
+
retryBackoff?: boolean | null;
|
|
1171
|
+
retryDelayMax?: number | null;
|
|
866
1172
|
}
|
|
867
1173
|
/**
|
|
868
1174
|
* Input shape for creating a cron schedule in the backend.
|
|
@@ -881,6 +1187,9 @@ interface CronScheduleInput {
|
|
|
881
1187
|
timezone: string;
|
|
882
1188
|
allowOverlap: boolean;
|
|
883
1189
|
nextRunAt: Date | null;
|
|
1190
|
+
retryDelay: number | null;
|
|
1191
|
+
retryBackoff: boolean | null;
|
|
1192
|
+
retryDelayMax: number | null;
|
|
884
1193
|
}
|
|
885
1194
|
/**
|
|
886
1195
|
* Abstract backend interface that both PostgreSQL and Redis implement.
|
|
@@ -888,8 +1197,26 @@ interface CronScheduleInput {
|
|
|
888
1197
|
* and public API are backend-agnostic.
|
|
889
1198
|
*/
|
|
890
1199
|
interface QueueBackend {
|
|
891
|
-
/**
|
|
892
|
-
|
|
1200
|
+
/**
|
|
1201
|
+
* Add a job and return its numeric ID.
|
|
1202
|
+
*
|
|
1203
|
+
* @param job - Job configuration.
|
|
1204
|
+
* @param options - Optional. Pass `{ db }` to run the INSERT on an external
|
|
1205
|
+
* client (e.g., inside a transaction). PostgreSQL only.
|
|
1206
|
+
*/
|
|
1207
|
+
addJob<PayloadMap, T extends JobType<PayloadMap>>(job: JobOptions<PayloadMap, T>, options?: AddJobOptions): Promise<number>;
|
|
1208
|
+
/**
|
|
1209
|
+
* Add multiple jobs in a single operation and return their IDs.
|
|
1210
|
+
*
|
|
1211
|
+
* IDs are returned in the same order as the input array.
|
|
1212
|
+
* Each job may independently have an `idempotencyKey`; duplicates
|
|
1213
|
+
* resolve to the existing job's ID without creating a new row.
|
|
1214
|
+
*
|
|
1215
|
+
* @param jobs - Array of job configurations.
|
|
1216
|
+
* @param options - Optional. Pass `{ db }` to run the INSERTs on an external
|
|
1217
|
+
* client (e.g., inside a transaction). PostgreSQL only.
|
|
1218
|
+
*/
|
|
1219
|
+
addJobs<PayloadMap, T extends JobType<PayloadMap>>(jobs: JobOptions<PayloadMap, T>[], options?: AddJobOptions): Promise<number[]>;
|
|
893
1220
|
/** Get a single job by ID, or null if not found. */
|
|
894
1221
|
getJob<PayloadMap, T extends JobType<PayloadMap>>(id: number): Promise<JobRecord<PayloadMap, T> | null>;
|
|
895
1222
|
/** Get jobs filtered by status, ordered by createdAt DESC. */
|
|
@@ -905,8 +1232,8 @@ interface QueueBackend {
|
|
|
905
1232
|
* Equivalent to SELECT … FOR UPDATE SKIP LOCKED in Postgres.
|
|
906
1233
|
*/
|
|
907
1234
|
getNextBatch<PayloadMap, T extends JobType<PayloadMap>>(workerId: string, batchSize?: number, jobType?: string | string[]): Promise<JobRecord<PayloadMap, T>[]>;
|
|
908
|
-
/** Mark a job as completed. */
|
|
909
|
-
completeJob(jobId: number): Promise<void>;
|
|
1235
|
+
/** Mark a job as completed, optionally storing output data. */
|
|
1236
|
+
completeJob(jobId: number, output?: unknown): Promise<void>;
|
|
910
1237
|
/** Mark a job as failed with error info and schedule retry. */
|
|
911
1238
|
failJob(jobId: number, error: Error, failureReason?: FailureReason): Promise<void>;
|
|
912
1239
|
/** Update locked_at to keep the job alive (heartbeat). */
|
|
@@ -929,6 +1256,8 @@ interface QueueBackend {
|
|
|
929
1256
|
reclaimStuckJobs(maxProcessingTimeMinutes?: number): Promise<number>;
|
|
930
1257
|
/** Update the progress percentage (0-100) for a job. */
|
|
931
1258
|
updateProgress(jobId: number, progress: number): Promise<void>;
|
|
1259
|
+
/** Update the output data for a job. Best-effort: should not throw. */
|
|
1260
|
+
updateOutput(jobId: number, output: unknown): Promise<void>;
|
|
932
1261
|
/** Record a job event. Should not throw. */
|
|
933
1262
|
recordJobEvent(jobId: number, eventType: JobEventType, metadata?: any): Promise<void>;
|
|
934
1263
|
/** Get all events for a job, ordered by createdAt ASC. */
|
|
@@ -1022,17 +1351,33 @@ declare class PostgresBackend implements QueueBackend {
|
|
|
1022
1351
|
getPool(): Pool;
|
|
1023
1352
|
recordJobEvent(jobId: number, eventType: JobEventType, metadata?: any): Promise<void>;
|
|
1024
1353
|
getJobEvents(jobId: number): Promise<JobEvent[]>;
|
|
1025
|
-
|
|
1354
|
+
/**
|
|
1355
|
+
* Add a job and return its numeric ID.
|
|
1356
|
+
*
|
|
1357
|
+
* @param job - Job configuration.
|
|
1358
|
+
* @param options - Optional. Pass `{ db }` to run the INSERT on an external
|
|
1359
|
+
* client (e.g., inside a transaction) so the job is part of the caller's
|
|
1360
|
+
* transaction. The event INSERT also uses the same client.
|
|
1361
|
+
*/
|
|
1362
|
+
addJob<PayloadMap, T extends JobType<PayloadMap>>({ jobType, payload, maxAttempts, priority, runAt, timeoutMs, forceKillOnTimeout, tags, idempotencyKey, retryDelay, retryBackoff, retryDelayMax, }: JobOptions<PayloadMap, T>, options?: AddJobOptions): Promise<number>;
|
|
1363
|
+
/**
|
|
1364
|
+
* Insert multiple jobs in a single database round-trip.
|
|
1365
|
+
*
|
|
1366
|
+
* Uses a multi-row INSERT with ON CONFLICT handling for idempotency keys.
|
|
1367
|
+
* Returns IDs in the same order as the input array.
|
|
1368
|
+
*/
|
|
1369
|
+
addJobs<PayloadMap, T extends JobType<PayloadMap>>(jobs: JobOptions<PayloadMap, T>[], options?: AddJobOptions): Promise<number[]>;
|
|
1026
1370
|
getJob<PayloadMap, T extends JobType<PayloadMap>>(id: number): Promise<JobRecord<PayloadMap, T> | null>;
|
|
1027
1371
|
getJobsByStatus<PayloadMap, T extends JobType<PayloadMap>>(status: string, limit?: number, offset?: number): Promise<JobRecord<PayloadMap, T>[]>;
|
|
1028
1372
|
getAllJobs<PayloadMap, T extends JobType<PayloadMap>>(limit?: number, offset?: number): Promise<JobRecord<PayloadMap, T>[]>;
|
|
1029
1373
|
getJobs<PayloadMap, T extends JobType<PayloadMap>>(filters?: JobFilters, limit?: number, offset?: number): Promise<JobRecord<PayloadMap, T>[]>;
|
|
1030
1374
|
getJobsByTags<PayloadMap, T extends JobType<PayloadMap>>(tags: string[], mode?: TagQueryMode, limit?: number, offset?: number): Promise<JobRecord<PayloadMap, T>[]>;
|
|
1031
1375
|
getNextBatch<PayloadMap, T extends JobType<PayloadMap>>(workerId: string, batchSize?: number, jobType?: string | string[]): Promise<JobRecord<PayloadMap, T>[]>;
|
|
1032
|
-
completeJob(jobId: number): Promise<void>;
|
|
1376
|
+
completeJob(jobId: number, output?: unknown): Promise<void>;
|
|
1033
1377
|
failJob(jobId: number, error: Error, failureReason?: FailureReason): Promise<void>;
|
|
1034
1378
|
prolongJob(jobId: number): Promise<void>;
|
|
1035
1379
|
updateProgress(jobId: number, progress: number): Promise<void>;
|
|
1380
|
+
updateOutput(jobId: number, output: unknown): Promise<void>;
|
|
1036
1381
|
retryJob(jobId: number): Promise<void>;
|
|
1037
1382
|
cancelJob(jobId: number): Promise<void>;
|
|
1038
1383
|
cancelAllUpcomingJobs(filters?: JobFilters): Promise<number>;
|
|
@@ -1217,7 +1562,9 @@ declare function validateCronExpression(cronExpression: string, CronImpl?: typeo
|
|
|
1217
1562
|
* Initialize the job queue system.
|
|
1218
1563
|
*
|
|
1219
1564
|
* Defaults to PostgreSQL when `backend` is omitted.
|
|
1565
|
+
* For PostgreSQL, provide either `databaseConfig` or `pool` (bring your own).
|
|
1566
|
+
* For Redis, provide either `redisConfig` or `client` (bring your own).
|
|
1220
1567
|
*/
|
|
1221
1568
|
declare const initJobQueue: <PayloadMap = any>(config: JobQueueConfig) => JobQueue<PayloadMap>;
|
|
1222
1569
|
|
|
1223
|
-
export { type CreateTokenOptions, type CronScheduleInput, type CronScheduleOptions, type CronScheduleRecord, type CronScheduleStatus, type DatabaseSSLConfig, type EditCronScheduleOptions, type EditJobOptions, FailureReason, type JobContext, type JobEvent, JobEventType, type JobHandler, type JobHandlers, type JobOptions, type JobQueue, type JobQueueConfig, type JobQueueConfigLegacy, type JobRecord, type JobStatus, type JobType, type OnTimeoutCallback, PostgresBackend, type PostgresJobQueueConfig, type Processor, type ProcessorOptions, type QueueBackend, type RedisJobQueueConfig, type RedisTLSConfig, type TagQueryMode, type WaitDuration, WaitSignal, type WaitToken, type WaitTokenResult, type WaitpointRecord, type WaitpointStatus, getNextCronOccurrence, initJobQueue, testHandlerSerialization, validateCronExpression, validateHandlerSerializable };
|
|
1570
|
+
export { type AddJobOptions, type CreateTokenOptions, type CronScheduleInput, type CronScheduleOptions, type CronScheduleRecord, type CronScheduleStatus, type DatabaseClient, type DatabaseSSLConfig, type EditCronScheduleOptions, type EditJobOptions, FailureReason, type JobContext, type JobEvent, JobEventType, type JobHandler, type JobHandlers, type JobOptions, type JobQueue, type JobQueueConfig, type JobQueueConfigLegacy, type JobRecord, type JobStatus, type JobType, type OnTimeoutCallback, PostgresBackend, type PostgresJobQueueConfig, type Processor, type ProcessorOptions, type QueueBackend, type QueueEmitFn, type QueueEventMap, type QueueEventName, type RedisJobQueueConfig, type RedisTLSConfig, type Supervisor, type SupervisorOptions, type SupervisorRunResult, type TagQueryMode, type WaitDuration, WaitSignal, type WaitToken, type WaitTokenResult, type WaitpointRecord, type WaitpointStatus, getNextCronOccurrence, initJobQueue, testHandlerSerialization, validateCronExpression, validateHandlerSerializable };
|