@nicnocquee/dataqueue 1.30.0 → 1.31.0
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.cjs +769 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +216 -1
- package/dist/index.d.ts +216 -1
- package/dist/index.js +768 -4
- package/dist/index.js.map +1 -1
- package/migrations/1781200000004_create_cron_schedules_table.sql +33 -0
- package/package.json +3 -2
- package/src/backend.ts +69 -0
- package/src/backends/postgres.ts +331 -1
- package/src/backends/redis.test.ts +350 -0
- package/src/backends/redis.ts +389 -1
- package/src/cron.test.ts +126 -0
- package/src/cron.ts +40 -0
- package/src/index.test.ts +361 -0
- package/src/index.ts +157 -4
- package/src/processor.ts +22 -4
- package/src/types.ts +149 -0
package/src/types.ts
CHANGED
|
@@ -533,6 +533,90 @@ export type JobQueueConfigLegacy = PostgresJobQueueConfig;
|
|
|
533
533
|
|
|
534
534
|
export type TagQueryMode = 'exact' | 'all' | 'any' | 'none';
|
|
535
535
|
|
|
536
|
+
// ── Cron schedule types ──────────────────────────────────────────────
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Status of a cron schedule.
|
|
540
|
+
*/
|
|
541
|
+
export type CronScheduleStatus = 'active' | 'paused';
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Options for creating a recurring cron schedule.
|
|
545
|
+
* Each schedule defines a recurring job that is automatically enqueued
|
|
546
|
+
* when its cron expression matches.
|
|
547
|
+
*/
|
|
548
|
+
export interface CronScheduleOptions<
|
|
549
|
+
PayloadMap,
|
|
550
|
+
T extends JobType<PayloadMap>,
|
|
551
|
+
> {
|
|
552
|
+
/** Unique human-readable name for the schedule. */
|
|
553
|
+
scheduleName: string;
|
|
554
|
+
/** Standard cron expression (5 fields, e.g. "0 * * * *"). */
|
|
555
|
+
cronExpression: string;
|
|
556
|
+
/** Job type from the PayloadMap. */
|
|
557
|
+
jobType: T;
|
|
558
|
+
/** Payload for each job instance. */
|
|
559
|
+
payload: PayloadMap[T];
|
|
560
|
+
/** Maximum retry attempts for each job instance (default: 3). */
|
|
561
|
+
maxAttempts?: number;
|
|
562
|
+
/** Priority for each job instance (default: 0). */
|
|
563
|
+
priority?: number;
|
|
564
|
+
/** Timeout in milliseconds for each job instance. */
|
|
565
|
+
timeoutMs?: number;
|
|
566
|
+
/** Whether to force-kill the job on timeout (default: false). */
|
|
567
|
+
forceKillOnTimeout?: boolean;
|
|
568
|
+
/** Tags for each job instance. */
|
|
569
|
+
tags?: string[];
|
|
570
|
+
/** IANA timezone string for cron evaluation (default: "UTC"). */
|
|
571
|
+
timezone?: string;
|
|
572
|
+
/**
|
|
573
|
+
* Whether to allow overlapping job instances (default: false).
|
|
574
|
+
* When false, a new job will not be enqueued if the previous instance
|
|
575
|
+
* is still pending, processing, or waiting.
|
|
576
|
+
*/
|
|
577
|
+
allowOverlap?: boolean;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* A persisted cron schedule record.
|
|
582
|
+
*/
|
|
583
|
+
export interface CronScheduleRecord {
|
|
584
|
+
id: number;
|
|
585
|
+
scheduleName: string;
|
|
586
|
+
cronExpression: string;
|
|
587
|
+
jobType: string;
|
|
588
|
+
payload: any;
|
|
589
|
+
maxAttempts: number;
|
|
590
|
+
priority: number;
|
|
591
|
+
timeoutMs: number | null;
|
|
592
|
+
forceKillOnTimeout: boolean;
|
|
593
|
+
tags: string[] | undefined;
|
|
594
|
+
timezone: string;
|
|
595
|
+
allowOverlap: boolean;
|
|
596
|
+
status: CronScheduleStatus;
|
|
597
|
+
lastEnqueuedAt: Date | null;
|
|
598
|
+
lastJobId: number | null;
|
|
599
|
+
nextRunAt: Date | null;
|
|
600
|
+
createdAt: Date;
|
|
601
|
+
updatedAt: Date;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Options for editing an existing cron schedule.
|
|
606
|
+
* All fields are optional; only provided fields are updated.
|
|
607
|
+
*/
|
|
608
|
+
export interface EditCronScheduleOptions {
|
|
609
|
+
cronExpression?: string;
|
|
610
|
+
payload?: any;
|
|
611
|
+
maxAttempts?: number;
|
|
612
|
+
priority?: number;
|
|
613
|
+
timeoutMs?: number | null;
|
|
614
|
+
forceKillOnTimeout?: boolean;
|
|
615
|
+
tags?: string[] | null;
|
|
616
|
+
timezone?: string;
|
|
617
|
+
allowOverlap?: boolean;
|
|
618
|
+
}
|
|
619
|
+
|
|
536
620
|
export interface JobQueue<PayloadMap> {
|
|
537
621
|
/**
|
|
538
622
|
* Add a job to the job queue.
|
|
@@ -733,6 +817,71 @@ export interface JobQueue<PayloadMap> {
|
|
|
733
817
|
*/
|
|
734
818
|
expireTimedOutTokens: () => Promise<number>;
|
|
735
819
|
|
|
820
|
+
// ── Cron schedule operations ────────────────────────────────────────
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Add a recurring cron schedule. The processor automatically enqueues
|
|
824
|
+
* due cron jobs before each batch, so no manual triggering is needed.
|
|
825
|
+
*
|
|
826
|
+
* @returns The ID of the created schedule.
|
|
827
|
+
* @throws If the cron expression is invalid or the schedule name is already taken.
|
|
828
|
+
*/
|
|
829
|
+
addCronJob: <T extends JobType<PayloadMap>>(
|
|
830
|
+
options: CronScheduleOptions<PayloadMap, T>,
|
|
831
|
+
) => Promise<number>;
|
|
832
|
+
|
|
833
|
+
/**
|
|
834
|
+
* Get a cron schedule by its ID.
|
|
835
|
+
*/
|
|
836
|
+
getCronJob: (id: number) => Promise<CronScheduleRecord | null>;
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* Get a cron schedule by its unique name.
|
|
840
|
+
*/
|
|
841
|
+
getCronJobByName: (name: string) => Promise<CronScheduleRecord | null>;
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* List all cron schedules, optionally filtered by status.
|
|
845
|
+
*/
|
|
846
|
+
listCronJobs: (status?: CronScheduleStatus) => Promise<CronScheduleRecord[]>;
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Remove a cron schedule by its ID. Does not cancel any already-enqueued jobs.
|
|
850
|
+
*/
|
|
851
|
+
removeCronJob: (id: number) => Promise<void>;
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* Pause a cron schedule. Paused schedules are skipped by `enqueueDueCronJobs()`.
|
|
855
|
+
*/
|
|
856
|
+
pauseCronJob: (id: number) => Promise<void>;
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Resume a paused cron schedule.
|
|
860
|
+
*/
|
|
861
|
+
resumeCronJob: (id: number) => Promise<void>;
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Edit an existing cron schedule. Only provided fields are updated.
|
|
865
|
+
* If `cronExpression` or `timezone` changes, `nextRunAt` is recalculated.
|
|
866
|
+
*/
|
|
867
|
+
editCronJob: (id: number, updates: EditCronScheduleOptions) => Promise<void>;
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Check all active cron schedules and enqueue jobs for any whose
|
|
871
|
+
* `nextRunAt` has passed. When `allowOverlap` is false (the default),
|
|
872
|
+
* a new job is not enqueued if the previous instance is still
|
|
873
|
+
* pending, processing, or waiting.
|
|
874
|
+
*
|
|
875
|
+
* **Note:** The processor calls this automatically before each batch,
|
|
876
|
+
* so you typically do not need to call it yourself. It is exposed for
|
|
877
|
+
* manual use in tests or one-off scripts.
|
|
878
|
+
*
|
|
879
|
+
* @returns The number of jobs that were enqueued.
|
|
880
|
+
*/
|
|
881
|
+
enqueueDueCronJobs: () => Promise<number>;
|
|
882
|
+
|
|
883
|
+
// ── Advanced access ───────────────────────────────────────────────────
|
|
884
|
+
|
|
736
885
|
/**
|
|
737
886
|
* Get the PostgreSQL database pool.
|
|
738
887
|
* Throws if the backend is not PostgreSQL.
|