@monque/core 1.0.0 → 1.1.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/LICENSE +15 -0
- package/README.md +20 -0
- package/dist/CHANGELOG.md +83 -0
- package/dist/LICENSE +15 -0
- package/dist/README.md +150 -0
- package/dist/index.cjs +2209 -942
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +537 -280
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +538 -281
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2213 -951
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -8
- package/src/events/index.ts +1 -0
- package/src/events/types.ts +113 -0
- package/src/index.ts +51 -0
- package/src/jobs/guards.ts +220 -0
- package/src/jobs/index.ts +29 -0
- package/src/jobs/types.ts +335 -0
- package/src/reset.d.ts +1 -0
- package/src/scheduler/helpers.ts +107 -0
- package/src/scheduler/index.ts +5 -0
- package/src/scheduler/monque.ts +1309 -0
- package/src/scheduler/services/change-stream-handler.ts +239 -0
- package/src/scheduler/services/index.ts +8 -0
- package/src/scheduler/services/job-manager.ts +455 -0
- package/src/scheduler/services/job-processor.ts +301 -0
- package/src/scheduler/services/job-query.ts +411 -0
- package/src/scheduler/services/job-scheduler.ts +267 -0
- package/src/scheduler/services/types.ts +48 -0
- package/src/scheduler/types.ts +123 -0
- package/src/shared/errors.ts +225 -0
- package/src/shared/index.ts +18 -0
- package/src/shared/utils/backoff.ts +77 -0
- package/src/shared/utils/cron.ts +67 -0
- package/src/shared/utils/index.ts +7 -0
- package/src/workers/index.ts +1 -0
- package/src/workers/types.ts +39 -0
- package/dist/errors-D5ZGG2uI.cjs +0 -155
- package/dist/errors-D5ZGG2uI.cjs.map +0 -1
- package/dist/errors-DEvnqoOC.mjs +0 -3
- package/dist/errors-DQ2_gprw.mjs +0 -125
- package/dist/errors-DQ2_gprw.mjs.map +0 -1
- package/dist/errors-Dfli-u59.cjs +0 -3
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,6 @@ import { Db, ObjectId } from "mongodb";
|
|
|
2
2
|
import { EventEmitter } from "node:events";
|
|
3
3
|
|
|
4
4
|
//#region src/jobs/types.d.ts
|
|
5
|
-
|
|
6
5
|
/**
|
|
7
6
|
* Represents the lifecycle states of a job in the queue.
|
|
8
7
|
*
|
|
@@ -11,6 +10,7 @@ import { EventEmitter } from "node:events";
|
|
|
11
10
|
* - PROCESSING → COMPLETED (on success)
|
|
12
11
|
* - PROCESSING → PENDING (on failure, if retries remain)
|
|
13
12
|
* - PROCESSING → FAILED (on failure, after max retries exhausted)
|
|
13
|
+
* - PENDING → CANCELLED (on manual cancellation)
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```typescript
|
|
@@ -20,17 +20,14 @@ import { EventEmitter } from "node:events";
|
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
22
|
declare const JobStatus: {
|
|
23
|
-
/** Job is waiting to be picked up by a worker */
|
|
24
|
-
readonly
|
|
25
|
-
/** Job
|
|
26
|
-
readonly
|
|
27
|
-
|
|
28
|
-
readonly COMPLETED: "completed";
|
|
29
|
-
/** Job permanently failed after exhausting all retry attempts */
|
|
30
|
-
readonly FAILED: "failed";
|
|
23
|
+
/** Job is waiting to be picked up by a worker */readonly PENDING: "pending"; /** Job is currently being executed by a worker */
|
|
24
|
+
readonly PROCESSING: "processing"; /** Job completed successfully */
|
|
25
|
+
readonly COMPLETED: "completed"; /** Job permanently failed after exhausting all retry attempts */
|
|
26
|
+
readonly FAILED: "failed"; /** Job was manually cancelled */
|
|
27
|
+
readonly CANCELLED: "cancelled";
|
|
31
28
|
};
|
|
32
29
|
/**
|
|
33
|
-
* Union type of all possible job status values: `'pending' | 'processing' | 'completed' | 'failed'`
|
|
30
|
+
* Union type of all possible job status values: `'pending' | 'processing' | 'completed' | 'failed' | 'cancelled'`
|
|
34
31
|
*/
|
|
35
32
|
type JobStatusType = (typeof JobStatus)[keyof typeof JobStatus];
|
|
36
33
|
/**
|
|
@@ -192,6 +189,120 @@ interface GetJobsFilter {
|
|
|
192
189
|
* ```
|
|
193
190
|
*/
|
|
194
191
|
type JobHandler<T = unknown> = (job: Job<T>) => Promise<void> | void;
|
|
192
|
+
/**
|
|
193
|
+
* Valid cursor directions for pagination.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* const direction = CursorDirection.FORWARD;
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
declare const CursorDirection: {
|
|
201
|
+
readonly FORWARD: "forward";
|
|
202
|
+
readonly BACKWARD: "backward";
|
|
203
|
+
};
|
|
204
|
+
type CursorDirectionType = (typeof CursorDirection)[keyof typeof CursorDirection];
|
|
205
|
+
/**
|
|
206
|
+
* Selector options for bulk operations.
|
|
207
|
+
*
|
|
208
|
+
* Used to select multiple jobs for operations like cancellation or deletion.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```typescript
|
|
212
|
+
* // Select all failed jobs older than 7 days
|
|
213
|
+
* const selector: JobSelector = {
|
|
214
|
+
* status: JobStatus.FAILED,
|
|
215
|
+
* olderThan: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
|
|
216
|
+
* };
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
interface JobSelector {
|
|
220
|
+
name?: string;
|
|
221
|
+
status?: JobStatusType | JobStatusType[];
|
|
222
|
+
olderThan?: Date;
|
|
223
|
+
newerThan?: Date;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Options for cursor-based pagination.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```typescript
|
|
230
|
+
* const options: CursorOptions = {
|
|
231
|
+
* limit: 50,
|
|
232
|
+
* direction: CursorDirection.FORWARD,
|
|
233
|
+
* filter: { status: JobStatus.PENDING },
|
|
234
|
+
* };
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
interface CursorOptions {
|
|
238
|
+
cursor?: string;
|
|
239
|
+
limit?: number;
|
|
240
|
+
direction?: CursorDirectionType;
|
|
241
|
+
filter?: Pick<GetJobsFilter, 'name' | 'status'>;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Response structure for cursor-based pagination.
|
|
245
|
+
*
|
|
246
|
+
* @template T - The type of the job's data payload
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* const page = await monque.listJobs({ limit: 10 });
|
|
251
|
+
* console.log(`Got ${page.jobs.length} jobs`);
|
|
252
|
+
*
|
|
253
|
+
* if (page.hasNextPage) {
|
|
254
|
+
* console.log(`Next cursor: ${page.cursor}`);
|
|
255
|
+
* }
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
interface CursorPage<T = unknown> {
|
|
259
|
+
jobs: PersistedJob<T>[];
|
|
260
|
+
cursor: string | null;
|
|
261
|
+
hasNextPage: boolean;
|
|
262
|
+
hasPreviousPage: boolean;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Aggregated statistics for the job queue.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```typescript
|
|
269
|
+
* const stats = await monque.getQueueStats();
|
|
270
|
+
* console.log(`Total jobs: ${stats.total}`);
|
|
271
|
+
* console.log(`Pending: ${stats.pending}`);
|
|
272
|
+
* console.log(`Processing: ${stats.processing}`);
|
|
273
|
+
* console.log(`Failed: ${stats.failed}`);
|
|
274
|
+
* console.log(`Start to finish avg: ${stats.avgProcessingDurationMs}ms`);
|
|
275
|
+
* ```
|
|
276
|
+
*/
|
|
277
|
+
interface QueueStats {
|
|
278
|
+
pending: number;
|
|
279
|
+
processing: number;
|
|
280
|
+
completed: number;
|
|
281
|
+
failed: number;
|
|
282
|
+
cancelled: number;
|
|
283
|
+
total: number;
|
|
284
|
+
avgProcessingDurationMs?: number;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Result of a bulk operation.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* const result = await monque.cancelJobs(selector);
|
|
292
|
+
* console.log(`Cancelled ${result.count} jobs`);
|
|
293
|
+
*
|
|
294
|
+
* if (result.errors.length > 0) {
|
|
295
|
+
* console.warn('Some jobs could not be cancelled:', result.errors);
|
|
296
|
+
* }
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
interface BulkOperationResult {
|
|
300
|
+
count: number;
|
|
301
|
+
errors: Array<{
|
|
302
|
+
jobId: string;
|
|
303
|
+
error: string;
|
|
304
|
+
}>;
|
|
305
|
+
}
|
|
195
306
|
//#endregion
|
|
196
307
|
//#region src/jobs/guards.d.ts
|
|
197
308
|
/**
|
|
@@ -231,8 +342,8 @@ declare function isPersistedJob<T>(job: Job<T>): job is PersistedJob<T>;
|
|
|
231
342
|
/**
|
|
232
343
|
* Type guard to check if a value is a valid job status.
|
|
233
344
|
*
|
|
234
|
-
* Validates that a value is one of the
|
|
235
|
-
* `'processing'`, `'completed'`, or `'
|
|
345
|
+
* Validates that a value is one of the five valid job statuses: `'pending'`,
|
|
346
|
+
* `'processing'`, `'completed'`, `'failed'`, or `'cancelled'`. Useful for runtime validation
|
|
236
347
|
* of user input or external data.
|
|
237
348
|
*
|
|
238
349
|
* @param value - The value to check
|
|
@@ -344,6 +455,24 @@ declare function isCompletedJob<T>(job: Job<T>): boolean;
|
|
|
344
455
|
* ```
|
|
345
456
|
*/
|
|
346
457
|
declare function isFailedJob<T>(job: Job<T>): boolean;
|
|
458
|
+
/**
|
|
459
|
+
* Type guard to check if a job has been manually cancelled.
|
|
460
|
+
*
|
|
461
|
+
* A convenience helper for checking if a job was cancelled by an operator.
|
|
462
|
+
* Equivalent to `job.status === JobStatus.CANCELLED` but with better semantics.
|
|
463
|
+
*
|
|
464
|
+
* @template T - The type of the job's data payload
|
|
465
|
+
* @param job - The job to check
|
|
466
|
+
* @returns `true` if the job status is `'cancelled'`
|
|
467
|
+
*
|
|
468
|
+
* @example Filter cancelled jobs
|
|
469
|
+
* ```typescript
|
|
470
|
+
* const jobs = await monque.getJobs();
|
|
471
|
+
* const cancelledJobs = jobs.filter(isCancelledJob);
|
|
472
|
+
* console.log(`${cancelledJobs.length} jobs were cancelled`);
|
|
473
|
+
* ```
|
|
474
|
+
*/
|
|
475
|
+
declare function isCancelledJob<T>(job: Job<T>): boolean;
|
|
347
476
|
/**
|
|
348
477
|
* Type guard to check if a job is a recurring scheduled job.
|
|
349
478
|
*
|
|
@@ -384,8 +513,7 @@ interface MonqueEventMap {
|
|
|
384
513
|
* Emitted when a job finishes successfully.
|
|
385
514
|
*/
|
|
386
515
|
'job:complete': {
|
|
387
|
-
job: Job;
|
|
388
|
-
/** Processing duration in milliseconds */
|
|
516
|
+
job: Job; /** Processing duration in milliseconds */
|
|
389
517
|
duration: number;
|
|
390
518
|
};
|
|
391
519
|
/**
|
|
@@ -393,8 +521,7 @@ interface MonqueEventMap {
|
|
|
393
521
|
*/
|
|
394
522
|
'job:fail': {
|
|
395
523
|
job: Job;
|
|
396
|
-
error: Error;
|
|
397
|
-
/** Whether the job will be retried */
|
|
524
|
+
error: Error; /** Whether the job will be retried */
|
|
398
525
|
willRetry: boolean;
|
|
399
526
|
};
|
|
400
527
|
/**
|
|
@@ -430,6 +557,45 @@ interface MonqueEventMap {
|
|
|
430
557
|
'changestream:fallback': {
|
|
431
558
|
reason: string;
|
|
432
559
|
};
|
|
560
|
+
/**
|
|
561
|
+
* Emitted when a job is manually cancelled.
|
|
562
|
+
*/
|
|
563
|
+
'job:cancelled': {
|
|
564
|
+
job: Job;
|
|
565
|
+
};
|
|
566
|
+
/**
|
|
567
|
+
* Emitted when a job is manually retried.
|
|
568
|
+
*/
|
|
569
|
+
'job:retried': {
|
|
570
|
+
job: Job;
|
|
571
|
+
previousStatus: 'failed' | 'cancelled';
|
|
572
|
+
};
|
|
573
|
+
/**
|
|
574
|
+
* Emitted when a job is manually deleted.
|
|
575
|
+
*/
|
|
576
|
+
'job:deleted': {
|
|
577
|
+
jobId: string;
|
|
578
|
+
};
|
|
579
|
+
/**
|
|
580
|
+
* Emitted when multiple jobs are cancelled in bulk.
|
|
581
|
+
*/
|
|
582
|
+
'jobs:cancelled': {
|
|
583
|
+
jobIds: string[];
|
|
584
|
+
count: number;
|
|
585
|
+
};
|
|
586
|
+
/**
|
|
587
|
+
* Emitted when multiple jobs are retried in bulk.
|
|
588
|
+
*/
|
|
589
|
+
'jobs:retried': {
|
|
590
|
+
jobIds: string[];
|
|
591
|
+
count: number;
|
|
592
|
+
};
|
|
593
|
+
/**
|
|
594
|
+
* Emitted when multiple jobs are deleted in bulk.
|
|
595
|
+
*/
|
|
596
|
+
'jobs:deleted': {
|
|
597
|
+
count: number;
|
|
598
|
+
};
|
|
433
599
|
}
|
|
434
600
|
//#endregion
|
|
435
601
|
//#region src/workers/types.d.ts
|
|
@@ -575,62 +741,43 @@ interface MonqueOptions {
|
|
|
575
741
|
* stale job recovery, and event-driven observability. Built on native MongoDB driver.
|
|
576
742
|
*
|
|
577
743
|
* @example Complete lifecycle
|
|
578
|
-
*
|
|
579
|
-
|
|
744
|
+
* ```typescript
|
|
745
|
+
* import { Monque } from '@monque/core';
|
|
746
|
+
* import { MongoClient } from 'mongodb';
|
|
580
747
|
*
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
*
|
|
585
|
-
|
|
586
|
-
import { MongoClient } from 'mongodb';
|
|
587
|
-
|
|
588
|
-
*
|
|
748
|
+
* const client = new MongoClient('mongodb://localhost:27017');
|
|
749
|
+
* await client.connect();
|
|
750
|
+
* const db = client.db('myapp');
|
|
589
751
|
*
|
|
590
|
-
const client = new MongoClient('mongodb://localhost:27017');
|
|
591
|
-
* await client.connect()
|
|
592
|
-
*
|
|
593
|
-
const db = client.db('myapp');
|
|
594
|
-
*
|
|
595
752
|
* // Create instance with options
|
|
596
|
-
*
|
|
597
|
-
const monque = new Monque(db, {
|
|
753
|
+
* const monque = new Monque(db, {
|
|
598
754
|
* collectionName: 'jobs',
|
|
599
755
|
* pollInterval: 1000,
|
|
600
756
|
* maxRetries: 10,
|
|
601
757
|
* shutdownTimeout: 30000,
|
|
602
758
|
* });
|
|
603
|
-
*
|
|
759
|
+
*
|
|
604
760
|
* // Initialize (sets up indexes and recovers stale jobs)
|
|
605
|
-
* await monque.initialize()
|
|
606
|
-
*
|
|
761
|
+
* await monque.initialize();
|
|
762
|
+
*
|
|
607
763
|
* // Register workers with type safety
|
|
764
|
+
* type EmailJob = {
|
|
765
|
+
* to: string;
|
|
766
|
+
* subject: string;
|
|
767
|
+
* body: string;
|
|
768
|
+
* };
|
|
608
769
|
*
|
|
609
|
-
|
|
610
|
-
* to
|
|
611
|
-
*
|
|
612
|
-
* body: string
|
|
613
|
-
* }
|
|
770
|
+
* monque.register<EmailJob>('send-email', async (job) => {
|
|
771
|
+
* await emailService.send(job.data.to, job.data.subject, job.data.body);
|
|
772
|
+
* });
|
|
614
773
|
*
|
|
615
|
-
* monque.register<EmailJob>('send-email', async (job) =>
|
|
616
|
-
{
|
|
617
|
-
* await emailService.send(job.data.to, job.data.subject, job.data.body)
|
|
618
|
-
*
|
|
619
|
-
}
|
|
620
|
-
)
|
|
621
|
-
*
|
|
622
774
|
* // Monitor events for observability
|
|
623
|
-
* monque.on('job:complete', (
|
|
624
|
-
{
|
|
625
|
-
job, duration;
|
|
626
|
-
}
|
|
627
|
-
) =>
|
|
628
|
-
{
|
|
629
|
-
* logger.info(`Job $job.namecompleted in $durationms`);
|
|
775
|
+
* monque.on('job:complete', ({ job, duration }) => {
|
|
776
|
+
* logger.info(`Job ${job.name} completed in ${duration}ms`);
|
|
630
777
|
* });
|
|
631
778
|
*
|
|
632
779
|
* monque.on('job:fail', ({ job, error, willRetry }) => {
|
|
633
|
-
* logger.error(`Job $job.
|
|
780
|
+
* logger.error(`Job ${job.name} failed:`, error);
|
|
634
781
|
* });
|
|
635
782
|
*
|
|
636
783
|
* // Start processing
|
|
@@ -661,34 +808,11 @@ declare class Monque extends EventEmitter {
|
|
|
661
808
|
private cleanupIntervalId;
|
|
662
809
|
private isRunning;
|
|
663
810
|
private isInitialized;
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
private
|
|
669
|
-
/**
|
|
670
|
-
* Number of consecutive reconnection attempts for change stream.
|
|
671
|
-
* Used for exponential backoff during reconnection.
|
|
672
|
-
*/
|
|
673
|
-
private changeStreamReconnectAttempts;
|
|
674
|
-
/**
|
|
675
|
-
* Maximum reconnection attempts before falling back to polling-only mode.
|
|
676
|
-
*/
|
|
677
|
-
private readonly maxChangeStreamReconnectAttempts;
|
|
678
|
-
/**
|
|
679
|
-
* Debounce timer for change stream event processing.
|
|
680
|
-
* Prevents claim storms when multiple events arrive in quick succession.
|
|
681
|
-
*/
|
|
682
|
-
private changeStreamDebounceTimer;
|
|
683
|
-
/**
|
|
684
|
-
* Whether the scheduler is currently using change streams for notifications.
|
|
685
|
-
*/
|
|
686
|
-
private usingChangeStreams;
|
|
687
|
-
/**
|
|
688
|
-
* Timer ID for change stream reconnection with exponential backoff.
|
|
689
|
-
* Tracked to allow cancellation during shutdown.
|
|
690
|
-
*/
|
|
691
|
-
private changeStreamReconnectTimer;
|
|
811
|
+
private _scheduler;
|
|
812
|
+
private _manager;
|
|
813
|
+
private _query;
|
|
814
|
+
private _processor;
|
|
815
|
+
private _changeStreamHandler;
|
|
692
816
|
constructor(db: Db, options?: MonqueOptions);
|
|
693
817
|
/**
|
|
694
818
|
* Initialize the scheduler by setting up the MongoDB collection and indexes.
|
|
@@ -697,6 +821,20 @@ declare class Monque extends EventEmitter {
|
|
|
697
821
|
* @throws {ConnectionError} If collection or index creation fails
|
|
698
822
|
*/
|
|
699
823
|
initialize(): Promise<void>;
|
|
824
|
+
/** @throws {ConnectionError} if not initialized */
|
|
825
|
+
private get scheduler();
|
|
826
|
+
/** @throws {ConnectionError} if not initialized */
|
|
827
|
+
private get manager();
|
|
828
|
+
/** @throws {ConnectionError} if not initialized */
|
|
829
|
+
private get query();
|
|
830
|
+
/** @throws {ConnectionError} if not initialized */
|
|
831
|
+
private get processor();
|
|
832
|
+
/** @throws {ConnectionError} if not initialized */
|
|
833
|
+
private get changeStreamHandler();
|
|
834
|
+
/**
|
|
835
|
+
* Build the shared context for internal services.
|
|
836
|
+
*/
|
|
837
|
+
private buildContext;
|
|
700
838
|
/**
|
|
701
839
|
* Create required MongoDB indexes for efficient job processing.
|
|
702
840
|
*
|
|
@@ -846,6 +984,266 @@ declare class Monque extends EventEmitter {
|
|
|
846
984
|
* ```
|
|
847
985
|
*/
|
|
848
986
|
schedule<T>(cron: string, name: string, data: T, options?: ScheduleOptions): Promise<PersistedJob<T>>;
|
|
987
|
+
/**
|
|
988
|
+
* Cancel a pending or scheduled job.
|
|
989
|
+
*
|
|
990
|
+
* Sets the job status to 'cancelled' and emits a 'job:cancelled' event.
|
|
991
|
+
* If the job is already cancelled, this is a no-op and returns the job.
|
|
992
|
+
* Cannot cancel jobs that are currently 'processing', 'completed', or 'failed'.
|
|
993
|
+
*
|
|
994
|
+
* @param jobId - The ID of the job to cancel
|
|
995
|
+
* @returns The cancelled job, or null if not found
|
|
996
|
+
* @throws {JobStateError} If job is in an invalid state for cancellation
|
|
997
|
+
*
|
|
998
|
+
* @example Cancel a pending job
|
|
999
|
+
* ```typescript
|
|
1000
|
+
* const job = await monque.enqueue('report', { type: 'daily' });
|
|
1001
|
+
* await monque.cancelJob(job._id.toString());
|
|
1002
|
+
* ```
|
|
1003
|
+
*/
|
|
1004
|
+
cancelJob(jobId: string): Promise<PersistedJob<unknown> | null>;
|
|
1005
|
+
/**
|
|
1006
|
+
* Retry a failed or cancelled job.
|
|
1007
|
+
*
|
|
1008
|
+
* Resets the job to 'pending' status, clears failure count/reason, and sets
|
|
1009
|
+
* nextRunAt to now (immediate retry). Emits a 'job:retried' event.
|
|
1010
|
+
*
|
|
1011
|
+
* @param jobId - The ID of the job to retry
|
|
1012
|
+
* @returns The updated job, or null if not found
|
|
1013
|
+
* @throws {JobStateError} If job is in an invalid state for retry (must be failed or cancelled)
|
|
1014
|
+
*
|
|
1015
|
+
* @example Retry a failed job
|
|
1016
|
+
* ```typescript
|
|
1017
|
+
* monque.on('job:fail', async ({ job }) => {
|
|
1018
|
+
* console.log(`Job ${job._id} failed, retrying manually...`);
|
|
1019
|
+
* await monque.retryJob(job._id.toString());
|
|
1020
|
+
* });
|
|
1021
|
+
* ```
|
|
1022
|
+
*/
|
|
1023
|
+
retryJob(jobId: string): Promise<PersistedJob<unknown> | null>;
|
|
1024
|
+
/**
|
|
1025
|
+
* Reschedule a pending job to run at a different time.
|
|
1026
|
+
*
|
|
1027
|
+
* Only works for jobs in 'pending' status.
|
|
1028
|
+
*
|
|
1029
|
+
* @param jobId - The ID of the job to reschedule
|
|
1030
|
+
* @param runAt - The new Date when the job should run
|
|
1031
|
+
* @returns The updated job, or null if not found
|
|
1032
|
+
* @throws {JobStateError} If job is not in pending state
|
|
1033
|
+
*
|
|
1034
|
+
* @example Delay a job by 1 hour
|
|
1035
|
+
* ```typescript
|
|
1036
|
+
* const nextHour = new Date(Date.now() + 60 * 60 * 1000);
|
|
1037
|
+
* await monque.rescheduleJob(jobId, nextHour);
|
|
1038
|
+
* ```
|
|
1039
|
+
*/
|
|
1040
|
+
rescheduleJob(jobId: string, runAt: Date): Promise<PersistedJob<unknown> | null>;
|
|
1041
|
+
/**
|
|
1042
|
+
* Permanently delete a job.
|
|
1043
|
+
*
|
|
1044
|
+
* This action is irreversible. Emits a 'job:deleted' event upon success.
|
|
1045
|
+
* Can delete a job in any state.
|
|
1046
|
+
*
|
|
1047
|
+
* @param jobId - The ID of the job to delete
|
|
1048
|
+
* @returns true if deleted, false if job not found
|
|
1049
|
+
*
|
|
1050
|
+
* @example Delete a cleanup job
|
|
1051
|
+
* ```typescript
|
|
1052
|
+
* const deleted = await monque.deleteJob(jobId);
|
|
1053
|
+
* if (deleted) {
|
|
1054
|
+
* console.log('Job permanently removed');
|
|
1055
|
+
* }
|
|
1056
|
+
* ```
|
|
1057
|
+
*/
|
|
1058
|
+
deleteJob(jobId: string): Promise<boolean>;
|
|
1059
|
+
/**
|
|
1060
|
+
* Cancel multiple jobs matching the given filter.
|
|
1061
|
+
*
|
|
1062
|
+
* Only cancels jobs in 'pending' status. Jobs in other states are collected
|
|
1063
|
+
* as errors in the result. Emits a 'jobs:cancelled' event with the IDs of
|
|
1064
|
+
* successfully cancelled jobs.
|
|
1065
|
+
*
|
|
1066
|
+
* @param filter - Selector for which jobs to cancel (name, status, date range)
|
|
1067
|
+
* @returns Result with count of cancelled jobs and any errors encountered
|
|
1068
|
+
*
|
|
1069
|
+
* @example Cancel all pending jobs for a queue
|
|
1070
|
+
* ```typescript
|
|
1071
|
+
* const result = await monque.cancelJobs({
|
|
1072
|
+
* name: 'email-queue',
|
|
1073
|
+
* status: 'pending'
|
|
1074
|
+
* });
|
|
1075
|
+
* console.log(`Cancelled ${result.count} jobs`);
|
|
1076
|
+
* ```
|
|
1077
|
+
*/
|
|
1078
|
+
cancelJobs(filter: JobSelector): Promise<BulkOperationResult>;
|
|
1079
|
+
/**
|
|
1080
|
+
* Retry multiple jobs matching the given filter.
|
|
1081
|
+
*
|
|
1082
|
+
* Only retries jobs in 'failed' or 'cancelled' status. Jobs in other states
|
|
1083
|
+
* are collected as errors in the result. Emits a 'jobs:retried' event with
|
|
1084
|
+
* the IDs of successfully retried jobs.
|
|
1085
|
+
*
|
|
1086
|
+
* @param filter - Selector for which jobs to retry (name, status, date range)
|
|
1087
|
+
* @returns Result with count of retried jobs and any errors encountered
|
|
1088
|
+
*
|
|
1089
|
+
* @example Retry all failed jobs
|
|
1090
|
+
* ```typescript
|
|
1091
|
+
* const result = await monque.retryJobs({
|
|
1092
|
+
* status: 'failed'
|
|
1093
|
+
* });
|
|
1094
|
+
* console.log(`Retried ${result.count} jobs`);
|
|
1095
|
+
* ```
|
|
1096
|
+
*/
|
|
1097
|
+
retryJobs(filter: JobSelector): Promise<BulkOperationResult>;
|
|
1098
|
+
/**
|
|
1099
|
+
* Delete multiple jobs matching the given filter.
|
|
1100
|
+
*
|
|
1101
|
+
* Deletes jobs in any status. Uses a batch delete for efficiency.
|
|
1102
|
+
* Does not emit individual 'job:deleted' events to avoid noise.
|
|
1103
|
+
*
|
|
1104
|
+
* @param filter - Selector for which jobs to delete (name, status, date range)
|
|
1105
|
+
* @returns Result with count of deleted jobs (errors array always empty for delete)
|
|
1106
|
+
*
|
|
1107
|
+
* @example Delete old completed jobs
|
|
1108
|
+
* ```typescript
|
|
1109
|
+
* const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
|
|
1110
|
+
* const result = await monque.deleteJobs({
|
|
1111
|
+
* status: 'completed',
|
|
1112
|
+
* olderThan: weekAgo
|
|
1113
|
+
* });
|
|
1114
|
+
* console.log(`Deleted ${result.count} jobs`);
|
|
1115
|
+
* ```
|
|
1116
|
+
*/
|
|
1117
|
+
deleteJobs(filter: JobSelector): Promise<BulkOperationResult>;
|
|
1118
|
+
/**
|
|
1119
|
+
* Get a single job by its MongoDB ObjectId.
|
|
1120
|
+
*
|
|
1121
|
+
* Useful for retrieving job details when you have a job ID from events,
|
|
1122
|
+
* logs, or stored references.
|
|
1123
|
+
*
|
|
1124
|
+
* @template T - The expected type of the job data payload
|
|
1125
|
+
* @param id - The job's ObjectId
|
|
1126
|
+
* @returns Promise resolving to the job if found, null otherwise
|
|
1127
|
+
* @throws {ConnectionError} If scheduler not initialized
|
|
1128
|
+
*
|
|
1129
|
+
* @example Look up job from event
|
|
1130
|
+
* ```typescript
|
|
1131
|
+
* monque.on('job:fail', async ({ job }) => {
|
|
1132
|
+
* // Later, retrieve the job to check its status
|
|
1133
|
+
* const currentJob = await monque.getJob(job._id);
|
|
1134
|
+
* console.log(`Job status: ${currentJob?.status}`);
|
|
1135
|
+
* });
|
|
1136
|
+
* ```
|
|
1137
|
+
*
|
|
1138
|
+
* @example Admin endpoint
|
|
1139
|
+
* ```typescript
|
|
1140
|
+
* app.get('/jobs/:id', async (req, res) => {
|
|
1141
|
+
* const job = await monque.getJob(new ObjectId(req.params.id));
|
|
1142
|
+
* if (!job) {
|
|
1143
|
+
* return res.status(404).json({ error: 'Job not found' });
|
|
1144
|
+
* }
|
|
1145
|
+
* res.json(job);
|
|
1146
|
+
* });
|
|
1147
|
+
* ```
|
|
1148
|
+
*/
|
|
1149
|
+
getJob<T = unknown>(id: ObjectId): Promise<PersistedJob<T> | null>;
|
|
1150
|
+
/**
|
|
1151
|
+
* Query jobs from the queue with optional filters.
|
|
1152
|
+
*
|
|
1153
|
+
* Provides read-only access to job data for monitoring, debugging, and
|
|
1154
|
+
* administrative purposes. Results are ordered by `nextRunAt` ascending.
|
|
1155
|
+
*
|
|
1156
|
+
* @template T - The expected type of the job data payload
|
|
1157
|
+
* @param filter - Optional filter criteria
|
|
1158
|
+
* @returns Promise resolving to array of matching jobs
|
|
1159
|
+
* @throws {ConnectionError} If scheduler not initialized
|
|
1160
|
+
*
|
|
1161
|
+
* @example Get all pending jobs
|
|
1162
|
+
* ```typescript
|
|
1163
|
+
* const pendingJobs = await monque.getJobs({ status: JobStatus.PENDING });
|
|
1164
|
+
* console.log(`${pendingJobs.length} jobs waiting`);
|
|
1165
|
+
* ```
|
|
1166
|
+
*
|
|
1167
|
+
* @example Get failed email jobs
|
|
1168
|
+
* ```typescript
|
|
1169
|
+
* const failedEmails = await monque.getJobs({
|
|
1170
|
+
* name: 'send-email',
|
|
1171
|
+
* status: JobStatus.FAILED,
|
|
1172
|
+
* });
|
|
1173
|
+
* for (const job of failedEmails) {
|
|
1174
|
+
* console.error(`Job ${job._id} failed: ${job.failReason}`);
|
|
1175
|
+
* }
|
|
1176
|
+
* ```
|
|
1177
|
+
*
|
|
1178
|
+
* @example Paginated job listing
|
|
1179
|
+
* ```typescript
|
|
1180
|
+
* const page1 = await monque.getJobs({ limit: 50, skip: 0 });
|
|
1181
|
+
* const page2 = await monque.getJobs({ limit: 50, skip: 50 });
|
|
1182
|
+
* ```
|
|
1183
|
+
*
|
|
1184
|
+
* @example Use with type guards from @monque/core
|
|
1185
|
+
* ```typescript
|
|
1186
|
+
* import { isPendingJob, isRecurringJob } from '@monque/core';
|
|
1187
|
+
*
|
|
1188
|
+
* const jobs = await monque.getJobs();
|
|
1189
|
+
* const pendingRecurring = jobs.filter(job => isPendingJob(job) && isRecurringJob(job));
|
|
1190
|
+
* ```
|
|
1191
|
+
*/
|
|
1192
|
+
getJobs<T = unknown>(filter?: GetJobsFilter): Promise<PersistedJob<T>[]>;
|
|
1193
|
+
/**
|
|
1194
|
+
* Get a paginated list of jobs using opaque cursors.
|
|
1195
|
+
*
|
|
1196
|
+
* Provides stable pagination for large job lists. Supports forward and backward
|
|
1197
|
+
* navigation, filtering, and efficient database access via index-based cursor queries.
|
|
1198
|
+
*
|
|
1199
|
+
* @template T - The job data payload type
|
|
1200
|
+
* @param options - Pagination options (cursor, limit, direction, filter)
|
|
1201
|
+
* @returns Page of jobs with next/prev cursors
|
|
1202
|
+
* @throws {InvalidCursorError} If the provided cursor is malformed
|
|
1203
|
+
* @throws {ConnectionError} If database operation fails or scheduler not initialized
|
|
1204
|
+
*
|
|
1205
|
+
* @example List pending jobs
|
|
1206
|
+
* ```typescript
|
|
1207
|
+
* const page = await monque.getJobsWithCursor({
|
|
1208
|
+
* limit: 20,
|
|
1209
|
+
* filter: { status: 'pending' }
|
|
1210
|
+
* });
|
|
1211
|
+
* const jobs = page.jobs;
|
|
1212
|
+
*
|
|
1213
|
+
* // Get next page
|
|
1214
|
+
* if (page.hasNextPage) {
|
|
1215
|
+
* const page2 = await monque.getJobsWithCursor({
|
|
1216
|
+
* cursor: page.cursor,
|
|
1217
|
+
* limit: 20
|
|
1218
|
+
* });
|
|
1219
|
+
* }
|
|
1220
|
+
* ```
|
|
1221
|
+
*/
|
|
1222
|
+
getJobsWithCursor<T = unknown>(options?: CursorOptions): Promise<CursorPage<T>>;
|
|
1223
|
+
/**
|
|
1224
|
+
* Get aggregate statistics for the job queue.
|
|
1225
|
+
*
|
|
1226
|
+
* Uses MongoDB aggregation pipeline for efficient server-side calculation.
|
|
1227
|
+
* Returns counts per status and optional average processing duration for completed jobs.
|
|
1228
|
+
*
|
|
1229
|
+
* @param filter - Optional filter to scope statistics by job name
|
|
1230
|
+
* @returns Promise resolving to queue statistics
|
|
1231
|
+
* @throws {AggregationTimeoutError} If aggregation exceeds 30 second timeout
|
|
1232
|
+
* @throws {ConnectionError} If database operation fails
|
|
1233
|
+
*
|
|
1234
|
+
* @example Get overall queue statistics
|
|
1235
|
+
* ```typescript
|
|
1236
|
+
* const stats = await monque.getQueueStats();
|
|
1237
|
+
* console.log(`Pending: ${stats.pending}, Failed: ${stats.failed}`);
|
|
1238
|
+
* ```
|
|
1239
|
+
*
|
|
1240
|
+
* @example Get statistics for a specific job type
|
|
1241
|
+
* ```typescript
|
|
1242
|
+
* const emailStats = await monque.getQueueStats({ name: 'send-email' });
|
|
1243
|
+
* console.log(`${emailStats.total} email jobs in queue`);
|
|
1244
|
+
* ```
|
|
1245
|
+
*/
|
|
1246
|
+
getQueueStats(filter?: Pick<JobSelector, 'name'>): Promise<QueueStats>;
|
|
849
1247
|
/**
|
|
850
1248
|
* Register a worker to process jobs of a specific type.
|
|
851
1249
|
*
|
|
@@ -1036,144 +1434,6 @@ declare class Monque extends EventEmitter {
|
|
|
1036
1434
|
* ```
|
|
1037
1435
|
*/
|
|
1038
1436
|
isHealthy(): boolean;
|
|
1039
|
-
/**
|
|
1040
|
-
* Query jobs from the queue with optional filters.
|
|
1041
|
-
*
|
|
1042
|
-
* Provides read-only access to job data for monitoring, debugging, and
|
|
1043
|
-
* administrative purposes. Results are ordered by `nextRunAt` ascending.
|
|
1044
|
-
*
|
|
1045
|
-
* @template T - The expected type of the job data payload
|
|
1046
|
-
* @param filter - Optional filter criteria
|
|
1047
|
-
* @returns Promise resolving to array of matching jobs
|
|
1048
|
-
* @throws {ConnectionError} If scheduler not initialized
|
|
1049
|
-
*
|
|
1050
|
-
* @example Get all pending jobs
|
|
1051
|
-
* ```typescript
|
|
1052
|
-
* const pendingJobs = await monque.getJobs({ status: JobStatus.PENDING });
|
|
1053
|
-
* console.log(`${pendingJobs.length} jobs waiting`);
|
|
1054
|
-
* ```
|
|
1055
|
-
*
|
|
1056
|
-
* @example Get failed email jobs
|
|
1057
|
-
* ```typescript
|
|
1058
|
-
* const failedEmails = await monque.getJobs({
|
|
1059
|
-
* name: 'send-email',
|
|
1060
|
-
* status: JobStatus.FAILED,
|
|
1061
|
-
* });
|
|
1062
|
-
* for (const job of failedEmails) {
|
|
1063
|
-
* console.error(`Job ${job._id} failed: ${job.failReason}`);
|
|
1064
|
-
* }
|
|
1065
|
-
* ```
|
|
1066
|
-
*
|
|
1067
|
-
* @example Paginated job listing
|
|
1068
|
-
* ```typescript
|
|
1069
|
-
* const page1 = await monque.getJobs({ limit: 50, skip: 0 });
|
|
1070
|
-
* const page2 = await monque.getJobs({ limit: 50, skip: 50 });
|
|
1071
|
-
* ```
|
|
1072
|
-
*
|
|
1073
|
-
* @example Use with type guards from @monque/core
|
|
1074
|
-
* ```typescript
|
|
1075
|
-
* import { isPendingJob, isRecurringJob } from '@monque/core';
|
|
1076
|
-
*
|
|
1077
|
-
* const jobs = await monque.getJobs();
|
|
1078
|
-
* const pendingRecurring = jobs.filter(job => isPendingJob(job) && isRecurringJob(job));
|
|
1079
|
-
* ```
|
|
1080
|
-
*/
|
|
1081
|
-
getJobs<T = unknown>(filter?: GetJobsFilter): Promise<PersistedJob<T>[]>;
|
|
1082
|
-
/**
|
|
1083
|
-
* Get a single job by its MongoDB ObjectId.
|
|
1084
|
-
*
|
|
1085
|
-
* Useful for retrieving job details when you have a job ID from events,
|
|
1086
|
-
* logs, or stored references.
|
|
1087
|
-
*
|
|
1088
|
-
* @template T - The expected type of the job data payload
|
|
1089
|
-
* @param id - The job's ObjectId
|
|
1090
|
-
* @returns Promise resolving to the job if found, null otherwise
|
|
1091
|
-
* @throws {ConnectionError} If scheduler not initialized
|
|
1092
|
-
*
|
|
1093
|
-
* @example Look up job from event
|
|
1094
|
-
* ```typescript
|
|
1095
|
-
* monque.on('job:fail', async ({ job }) => {
|
|
1096
|
-
* // Later, retrieve the job to check its status
|
|
1097
|
-
* const currentJob = await monque.getJob(job._id);
|
|
1098
|
-
* console.log(`Job status: ${currentJob?.status}`);
|
|
1099
|
-
* });
|
|
1100
|
-
* ```
|
|
1101
|
-
*
|
|
1102
|
-
* @example Admin endpoint
|
|
1103
|
-
* ```typescript
|
|
1104
|
-
* app.get('/jobs/:id', async (req, res) => {
|
|
1105
|
-
* const job = await monque.getJob(new ObjectId(req.params.id));
|
|
1106
|
-
* if (!job) {
|
|
1107
|
-
* return res.status(404).json({ error: 'Job not found' });
|
|
1108
|
-
* }
|
|
1109
|
-
* res.json(job);
|
|
1110
|
-
* });
|
|
1111
|
-
* ```
|
|
1112
|
-
*/
|
|
1113
|
-
getJob<T = unknown>(id: ObjectId): Promise<PersistedJob<T> | null>;
|
|
1114
|
-
/**
|
|
1115
|
-
* Poll for available jobs and process them.
|
|
1116
|
-
*
|
|
1117
|
-
* Called at regular intervals (configured by `pollInterval`). For each registered worker,
|
|
1118
|
-
* attempts to acquire jobs up to the worker's available concurrency slots.
|
|
1119
|
-
* Aborts early if the scheduler is stopping (`isRunning` is false).
|
|
1120
|
-
*
|
|
1121
|
-
* @private
|
|
1122
|
-
*/
|
|
1123
|
-
private poll;
|
|
1124
|
-
/**
|
|
1125
|
-
* Atomically acquire a pending job for processing using the claimedBy pattern.
|
|
1126
|
-
*
|
|
1127
|
-
* Uses MongoDB's `findOneAndUpdate` with atomic operations to ensure only one scheduler
|
|
1128
|
-
* instance can claim a job. The query ensures the job is:
|
|
1129
|
-
* - In pending status
|
|
1130
|
-
* - Has nextRunAt <= now
|
|
1131
|
-
* - Is not claimed by another instance (claimedBy is null/undefined)
|
|
1132
|
-
*
|
|
1133
|
-
* Returns `null` immediately if scheduler is stopping (`isRunning` is false).
|
|
1134
|
-
*
|
|
1135
|
-
* @private
|
|
1136
|
-
* @param name - The job type to acquire
|
|
1137
|
-
* @returns The acquired job with updated status, claimedBy, and heartbeat info, or `null` if no jobs available
|
|
1138
|
-
*/
|
|
1139
|
-
private acquireJob;
|
|
1140
|
-
/**
|
|
1141
|
-
* Execute a job using its registered worker handler.
|
|
1142
|
-
*
|
|
1143
|
-
* Tracks the job as active during processing, emits lifecycle events, and handles
|
|
1144
|
-
* both success and failure cases. On success, calls `completeJob()`. On failure,
|
|
1145
|
-
* calls `failJob()` which implements exponential backoff retry logic.
|
|
1146
|
-
*
|
|
1147
|
-
* @private
|
|
1148
|
-
* @param job - The job to process
|
|
1149
|
-
* @param worker - The worker registration containing the handler and active job tracking
|
|
1150
|
-
*/
|
|
1151
|
-
private processJob;
|
|
1152
|
-
/**
|
|
1153
|
-
* Mark a job as completed successfully.
|
|
1154
|
-
*
|
|
1155
|
-
* For recurring jobs (with `repeatInterval`), schedules the next run based on the cron
|
|
1156
|
-
* expression and resets `failCount` to 0. For one-time jobs, sets status to `completed`.
|
|
1157
|
-
* Clears `lockedAt` and `failReason` fields in both cases.
|
|
1158
|
-
*
|
|
1159
|
-
* @private
|
|
1160
|
-
* @param job - The job that completed successfully
|
|
1161
|
-
*/
|
|
1162
|
-
private completeJob;
|
|
1163
|
-
/**
|
|
1164
|
-
* Handle job failure with exponential backoff retry logic.
|
|
1165
|
-
*
|
|
1166
|
-
* Increments `failCount` and calculates next retry time using exponential backoff:
|
|
1167
|
-
* `nextRunAt = 2^failCount × baseRetryInterval` (capped by optional `maxBackoffDelay`).
|
|
1168
|
-
*
|
|
1169
|
-
* If `failCount >= maxRetries`, marks job as permanently `failed`. Otherwise, resets
|
|
1170
|
-
* to `pending` status for retry. Stores error message in `failReason` field.
|
|
1171
|
-
*
|
|
1172
|
-
* @private
|
|
1173
|
-
* @param job - The job that failed
|
|
1174
|
-
* @param error - The error that caused the failure
|
|
1175
|
-
*/
|
|
1176
|
-
private failJob;
|
|
1177
1437
|
/**
|
|
1178
1438
|
* Ensure the scheduler is initialized before operations.
|
|
1179
1439
|
*
|
|
@@ -1181,63 +1441,6 @@ declare class Monque extends EventEmitter {
|
|
|
1181
1441
|
* @throws {ConnectionError} If scheduler not initialized or collection unavailable
|
|
1182
1442
|
*/
|
|
1183
1443
|
private ensureInitialized;
|
|
1184
|
-
/**
|
|
1185
|
-
* Update heartbeats for all jobs claimed by this scheduler instance.
|
|
1186
|
-
*
|
|
1187
|
-
* This method runs periodically while the scheduler is running to indicate
|
|
1188
|
-
* that jobs are still being actively processed.
|
|
1189
|
-
*
|
|
1190
|
-
* `lastHeartbeat` is primarily an observability signal (monitoring/debugging).
|
|
1191
|
-
* Stale recovery is based on `lockedAt` + `lockTimeout`.
|
|
1192
|
-
*
|
|
1193
|
-
* @private
|
|
1194
|
-
*/
|
|
1195
|
-
private updateHeartbeats;
|
|
1196
|
-
/**
|
|
1197
|
-
* Set up MongoDB Change Stream for real-time job notifications.
|
|
1198
|
-
*
|
|
1199
|
-
* Change streams provide instant notifications when jobs are inserted or when
|
|
1200
|
-
* job status changes to pending (e.g., after a retry). This eliminates the
|
|
1201
|
-
* polling delay for reactive job processing.
|
|
1202
|
-
*
|
|
1203
|
-
* The change stream watches for:
|
|
1204
|
-
* - Insert operations (new jobs)
|
|
1205
|
-
* - Update operations where status field changes
|
|
1206
|
-
*
|
|
1207
|
-
* If change streams are unavailable (e.g., standalone MongoDB), the system
|
|
1208
|
-
* gracefully falls back to polling-only mode.
|
|
1209
|
-
*
|
|
1210
|
-
* @private
|
|
1211
|
-
*/
|
|
1212
|
-
private setupChangeStream;
|
|
1213
|
-
/**
|
|
1214
|
-
* Handle a change stream event by triggering a debounced poll.
|
|
1215
|
-
*
|
|
1216
|
-
* Events are debounced to prevent "claim storms" when multiple changes arrive
|
|
1217
|
-
* in rapid succession (e.g., bulk job inserts). A 100ms debounce window
|
|
1218
|
-
* collects multiple events and triggers a single poll.
|
|
1219
|
-
*
|
|
1220
|
-
* @private
|
|
1221
|
-
* @param change - The change stream event document
|
|
1222
|
-
*/
|
|
1223
|
-
private handleChangeStreamEvent;
|
|
1224
|
-
/**
|
|
1225
|
-
* Handle change stream errors with exponential backoff reconnection.
|
|
1226
|
-
*
|
|
1227
|
-
* Attempts to reconnect up to `maxChangeStreamReconnectAttempts` times with
|
|
1228
|
-
* exponential backoff (base 1000ms). After exhausting retries, falls back to
|
|
1229
|
-
* polling-only mode.
|
|
1230
|
-
*
|
|
1231
|
-
* @private
|
|
1232
|
-
* @param error - The error that caused the change stream failure
|
|
1233
|
-
*/
|
|
1234
|
-
private handleChangeStreamError;
|
|
1235
|
-
/**
|
|
1236
|
-
* Close the change stream cursor and emit closed event.
|
|
1237
|
-
*
|
|
1238
|
-
* @private
|
|
1239
|
-
*/
|
|
1240
|
-
private closeChangeStream;
|
|
1241
1444
|
/**
|
|
1242
1445
|
* Get array of active job IDs across all workers.
|
|
1243
1446
|
*
|
|
@@ -1370,6 +1573,60 @@ declare class WorkerRegistrationError extends MonqueError {
|
|
|
1370
1573
|
readonly jobName: string;
|
|
1371
1574
|
constructor(message: string, jobName: string);
|
|
1372
1575
|
}
|
|
1576
|
+
/**
|
|
1577
|
+
* Error thrown when a state transition is invalid.
|
|
1578
|
+
*
|
|
1579
|
+
* @example
|
|
1580
|
+
* ```typescript
|
|
1581
|
+
* try {
|
|
1582
|
+
* await monque.cancelJob(jobId);
|
|
1583
|
+
* } catch (error) {
|
|
1584
|
+
* if (error instanceof JobStateError) {
|
|
1585
|
+
* console.error(`Cannot cancel job in state: ${error.currentStatus}`);
|
|
1586
|
+
* }
|
|
1587
|
+
* }
|
|
1588
|
+
* ```
|
|
1589
|
+
*/
|
|
1590
|
+
declare class JobStateError extends MonqueError {
|
|
1591
|
+
readonly jobId: string;
|
|
1592
|
+
readonly currentStatus: string;
|
|
1593
|
+
readonly attemptedAction: 'cancel' | 'retry' | 'reschedule';
|
|
1594
|
+
constructor(message: string, jobId: string, currentStatus: string, attemptedAction: 'cancel' | 'retry' | 'reschedule');
|
|
1595
|
+
}
|
|
1596
|
+
/**
|
|
1597
|
+
* Error thrown when a pagination cursor is invalid or malformed.
|
|
1598
|
+
*
|
|
1599
|
+
* @example
|
|
1600
|
+
* ```typescript
|
|
1601
|
+
* try {
|
|
1602
|
+
* await monque.listJobs({ cursor: 'invalid-cursor' });
|
|
1603
|
+
* } catch (error) {
|
|
1604
|
+
* if (error instanceof InvalidCursorError) {
|
|
1605
|
+
* console.error('Invalid cursor provided');
|
|
1606
|
+
* }
|
|
1607
|
+
* }
|
|
1608
|
+
* ```
|
|
1609
|
+
*/
|
|
1610
|
+
declare class InvalidCursorError extends MonqueError {
|
|
1611
|
+
constructor(message: string);
|
|
1612
|
+
}
|
|
1613
|
+
/**
|
|
1614
|
+
* Error thrown when a statistics aggregation times out.
|
|
1615
|
+
*
|
|
1616
|
+
* @example
|
|
1617
|
+
* ```typescript
|
|
1618
|
+
* try {
|
|
1619
|
+
* const stats = await monque.getQueueStats();
|
|
1620
|
+
* } catch (error) {
|
|
1621
|
+
* if (error instanceof AggregationTimeoutError) {
|
|
1622
|
+
* console.error('Stats took too long to calculate');
|
|
1623
|
+
* }
|
|
1624
|
+
* }
|
|
1625
|
+
* ```
|
|
1626
|
+
*/
|
|
1627
|
+
declare class AggregationTimeoutError extends MonqueError {
|
|
1628
|
+
constructor(message?: string);
|
|
1629
|
+
}
|
|
1373
1630
|
//#endregion
|
|
1374
1631
|
//#region src/shared/utils/backoff.d.ts
|
|
1375
1632
|
/**
|
|
@@ -1459,5 +1716,5 @@ declare function getNextCronDate(expression: string, currentDate?: Date): Date;
|
|
|
1459
1716
|
*/
|
|
1460
1717
|
declare function validateCronExpression(expression: string): void;
|
|
1461
1718
|
//#endregion
|
|
1462
|
-
export { ConnectionError, DEFAULT_BASE_INTERVAL, DEFAULT_MAX_BACKOFF_DELAY, type EnqueueOptions, type GetJobsFilter, InvalidCronError, type Job, type JobHandler, JobStatus, type JobStatusType, Monque, MonqueError, type MonqueEventMap, type MonqueOptions, type PersistedJob, type ScheduleOptions, ShutdownTimeoutError, type WorkerOptions, WorkerRegistrationError, calculateBackoff, calculateBackoffDelay, getNextCronDate, isCompletedJob, isFailedJob, isPendingJob, isPersistedJob, isProcessingJob, isRecurringJob, isValidJobStatus, validateCronExpression };
|
|
1719
|
+
export { AggregationTimeoutError, type BulkOperationResult, ConnectionError, CursorDirection, type CursorOptions, type CursorPage, DEFAULT_BASE_INTERVAL, DEFAULT_MAX_BACKOFF_DELAY, type EnqueueOptions, type GetJobsFilter, InvalidCronError, InvalidCursorError, type Job, type JobHandler, type JobSelector, JobStateError, JobStatus, type JobStatusType, Monque, MonqueError, type MonqueEventMap, type MonqueOptions, type PersistedJob, type QueueStats, type ScheduleOptions, ShutdownTimeoutError, type WorkerOptions, WorkerRegistrationError, calculateBackoff, calculateBackoffDelay, getNextCronDate, isCancelledJob, isCompletedJob, isFailedJob, isPendingJob, isPersistedJob, isProcessingJob, isRecurringJob, isValidJobStatus, validateCronExpression };
|
|
1463
1720
|
//# sourceMappingURL=index.d.cts.map
|