@boringnode/queue 0.0.1-alpha.4 → 0.2.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/README.md +156 -32
- package/build/{chunk-5PDDRF5O.js → chunk-NPQKBCCY.js} +2 -2
- package/build/{chunk-CD45GT6E.js → chunk-RIXMQXYJ.js} +5 -4
- package/build/chunk-RIXMQXYJ.js.map +1 -0
- package/build/{chunk-HMGNQSSG.js → chunk-SMOKFZ46.js} +15 -1
- package/build/chunk-SMOKFZ46.js.map +1 -0
- package/build/{index-C3_tlebh.d.ts → index-C0Xg6F4E.d.ts} +433 -35
- package/build/index.d.ts +81 -4
- package/build/index.js +428 -30
- package/build/index.js.map +1 -1
- package/build/src/contracts/adapter.d.ts +1 -1
- package/build/src/drivers/knex_adapter.d.ts +8 -1
- package/build/src/drivers/knex_adapter.js +186 -34
- package/build/src/drivers/knex_adapter.js.map +1 -1
- package/build/src/drivers/redis_adapter.d.ts +7 -1
- package/build/src/drivers/redis_adapter.js +193 -2
- package/build/src/drivers/redis_adapter.js.map +1 -1
- package/build/src/drivers/sync_adapter.d.ts +7 -1
- package/build/src/drivers/sync_adapter.js +24 -5
- package/build/src/drivers/sync_adapter.js.map +1 -1
- package/build/src/types/index.d.ts +1 -1
- package/build/src/types/main.d.ts +1 -1
- package/package.json +3 -2
- package/build/chunk-CD45GT6E.js.map +0 -1
- package/build/chunk-HMGNQSSG.js.map +0 -1
- /package/build/{chunk-5PDDRF5O.js.map → chunk-NPQKBCCY.js.map} +0 -0
|
@@ -185,23 +185,134 @@ interface Logger {
|
|
|
185
185
|
child(obj: LogObject): Logger;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Duration can be specified as milliseconds (number) or as a human-readable string.
|
|
190
|
+
*
|
|
191
|
+
* Supported string formats: '1s', '5m', '2h', '1d', etc.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```typescript
|
|
195
|
+
* const timeout: Duration = '30s' // 30 seconds
|
|
196
|
+
* const delay: Duration = 5000 // 5000 milliseconds
|
|
197
|
+
* const interval: Duration = '5m' // 5 minutes
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
188
200
|
type Duration = number | string;
|
|
201
|
+
/**
|
|
202
|
+
* Result returned when dispatching a job.
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```typescript
|
|
206
|
+
* const { jobId } = await SendEmailJob.dispatch(payload)
|
|
207
|
+
* console.log(`Dispatched job: ${jobId}`)
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
interface DispatchResult {
|
|
211
|
+
/** Unique identifier for this specific job instance */
|
|
212
|
+
jobId: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Internal representation of a job in the queue.
|
|
216
|
+
*
|
|
217
|
+
* This is used by adapters to store and retrieve job data.
|
|
218
|
+
* Not typically used directly by application code.
|
|
219
|
+
*/
|
|
189
220
|
interface JobData {
|
|
221
|
+
/**
|
|
222
|
+
* Unique identifier for this job.
|
|
223
|
+
*/
|
|
190
224
|
id: string;
|
|
225
|
+
/**
|
|
226
|
+
* Job class name.
|
|
227
|
+
*/
|
|
191
228
|
name: string;
|
|
229
|
+
/**
|
|
230
|
+
* Serialized job payload.
|
|
231
|
+
*/
|
|
192
232
|
payload: any;
|
|
233
|
+
/**
|
|
234
|
+
* Number of execution attempts so far.
|
|
235
|
+
*/
|
|
193
236
|
attempts: number;
|
|
237
|
+
/**
|
|
238
|
+
* Job priority (lower = higher priority).
|
|
239
|
+
*
|
|
240
|
+
* @default 0
|
|
241
|
+
*/
|
|
194
242
|
priority?: number;
|
|
243
|
+
/**
|
|
244
|
+
* When to retry this job next (for failed jobs).
|
|
245
|
+
*/
|
|
195
246
|
nextRetryAt?: Date;
|
|
247
|
+
/**
|
|
248
|
+
* Number of times this job was recovered from stalled state.
|
|
249
|
+
*/
|
|
196
250
|
stalledCount?: number;
|
|
197
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Static options for a Job class.
|
|
254
|
+
*
|
|
255
|
+
* Define these as a static property on your Job class to configure
|
|
256
|
+
* default behavior for all instances.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```typescript
|
|
260
|
+
* class SendEmailJob extends Job<EmailPayload> {
|
|
261
|
+
* static options: JobOptions = {
|
|
262
|
+
* name: 'SendEmailJob',
|
|
263
|
+
* queue: 'emails',
|
|
264
|
+
* maxRetries: 3,
|
|
265
|
+
* timeout: '30s',
|
|
266
|
+
* }
|
|
267
|
+
* }
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
198
270
|
interface JobOptions {
|
|
271
|
+
/**
|
|
272
|
+
* Unique name for this job class.
|
|
273
|
+
*
|
|
274
|
+
* Used to identify the job when dispatching and processing.
|
|
275
|
+
*
|
|
276
|
+
* @default constructor.name
|
|
277
|
+
*/
|
|
278
|
+
name?: string;
|
|
279
|
+
/**
|
|
280
|
+
* Queue name for this job.
|
|
281
|
+
*
|
|
282
|
+
* @default 'default'
|
|
283
|
+
*/
|
|
199
284
|
queue?: string;
|
|
285
|
+
/**
|
|
286
|
+
* Adapter name or factory to use for this job.
|
|
287
|
+
*/
|
|
200
288
|
adapter?: string | (() => Adapter);
|
|
289
|
+
/**
|
|
290
|
+
* Maximum retry attempts before permanent failure.
|
|
291
|
+
*
|
|
292
|
+
* @default 3
|
|
293
|
+
*/
|
|
201
294
|
maxRetries?: number;
|
|
295
|
+
/**
|
|
296
|
+
* Job priority (lower = higher priority).
|
|
297
|
+
*
|
|
298
|
+
* @default 0
|
|
299
|
+
*/
|
|
202
300
|
priority?: number;
|
|
301
|
+
/**
|
|
302
|
+
* Retry configuration (backoff strategy, delays, etc.).
|
|
303
|
+
*/
|
|
203
304
|
retry?: RetryConfig;
|
|
305
|
+
/**
|
|
306
|
+
* Maximum execution time before timeout.
|
|
307
|
+
*
|
|
308
|
+
* @default undefined (no timeout)
|
|
309
|
+
*/
|
|
204
310
|
timeout?: Duration;
|
|
311
|
+
/**
|
|
312
|
+
* Whether to mark job as failed on timeout.
|
|
313
|
+
*
|
|
314
|
+
* @default true
|
|
315
|
+
*/
|
|
205
316
|
failOnTimeout?: boolean;
|
|
206
317
|
}
|
|
207
318
|
/**
|
|
@@ -236,34 +347,39 @@ interface JobContext {
|
|
|
236
347
|
/** Number of times this job has been recovered from stalled state */
|
|
237
348
|
stalledCount: number;
|
|
238
349
|
}
|
|
239
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Type representing a Job class constructor.
|
|
352
|
+
*
|
|
353
|
+
* The constructor accepts any arguments for dependency injection.
|
|
354
|
+
* Payload and context are provided separately via `$hydrate()`.
|
|
355
|
+
*/
|
|
356
|
+
type JobClass<T extends Job = Job> = (new (...args: any[]) => T) & {
|
|
240
357
|
options?: JobOptions;
|
|
241
358
|
};
|
|
242
359
|
/**
|
|
243
360
|
* Factory function for custom job instantiation.
|
|
244
361
|
*
|
|
245
362
|
* Use this to integrate with IoC containers for dependency injection.
|
|
246
|
-
* The factory receives the job class
|
|
247
|
-
*
|
|
363
|
+
* The factory receives only the job class and should return an instance
|
|
364
|
+
* with all dependencies injected. The worker will call `$hydrate()` separately
|
|
365
|
+
* to provide payload, context, and signal.
|
|
248
366
|
*
|
|
249
367
|
* @param JobClass - The job class to instantiate
|
|
250
|
-
* @param payload - The payload data for the job
|
|
251
|
-
* @param context - The job execution context (jobId, attempt, queue, etc.)
|
|
252
368
|
* @returns The job instance, or a Promise resolving to the instance
|
|
253
369
|
*
|
|
254
370
|
* @example
|
|
255
371
|
* ```typescript
|
|
256
372
|
* // With AdonisJS IoC container
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
373
|
+
* await QueueManager.init({
|
|
374
|
+
* default: 'redis',
|
|
375
|
+
* adapters: { redis: redis() },
|
|
376
|
+
* jobFactory: async (JobClass) => {
|
|
377
|
+
* return app.container.make(JobClass)
|
|
262
378
|
* }
|
|
263
379
|
* })
|
|
264
380
|
* ```
|
|
265
381
|
*/
|
|
266
|
-
type JobFactory = (JobClass: JobClass
|
|
382
|
+
type JobFactory = (JobClass: JobClass) => Job | Promise<Job>;
|
|
267
383
|
interface RetryConfig {
|
|
268
384
|
maxRetries?: number;
|
|
269
385
|
backoff?: () => BackoffStrategy$1;
|
|
@@ -345,6 +461,82 @@ type WorkerCycle = {
|
|
|
345
461
|
suggestedDelay: Duration;
|
|
346
462
|
};
|
|
347
463
|
type AdapterFactory<T extends Adapter = Adapter> = () => T;
|
|
464
|
+
/**
|
|
465
|
+
* Status of a schedule.
|
|
466
|
+
*/
|
|
467
|
+
type ScheduleStatus = 'active' | 'paused';
|
|
468
|
+
/**
|
|
469
|
+
* Configuration for creating a schedule.
|
|
470
|
+
* Used by ScheduleBuilder to collect schedule options before creation.
|
|
471
|
+
*/
|
|
472
|
+
interface ScheduleConfig {
|
|
473
|
+
/** Optional ID for the schedule (UUID if not set). Used for upsert. */
|
|
474
|
+
id?: string;
|
|
475
|
+
/** Job class name */
|
|
476
|
+
name: string;
|
|
477
|
+
/** Job payload */
|
|
478
|
+
payload: any;
|
|
479
|
+
/** Cron expression (mutually exclusive with everyMs) */
|
|
480
|
+
cronExpression?: string;
|
|
481
|
+
/** Interval in milliseconds (mutually exclusive with cronExpression) */
|
|
482
|
+
everyMs?: number;
|
|
483
|
+
/** IANA timezone for cron evaluation */
|
|
484
|
+
timezone: string;
|
|
485
|
+
/** Start boundary - no jobs dispatched before this */
|
|
486
|
+
from?: Date;
|
|
487
|
+
/** End boundary - no jobs dispatched after this */
|
|
488
|
+
to?: Date;
|
|
489
|
+
/** Maximum number of runs (null = unlimited) */
|
|
490
|
+
limit?: number;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Persisted schedule data.
|
|
494
|
+
* Represents a schedule stored in the adapter.
|
|
495
|
+
*/
|
|
496
|
+
interface ScheduleData {
|
|
497
|
+
/** Unique identifier */
|
|
498
|
+
id: string;
|
|
499
|
+
/** Job class name */
|
|
500
|
+
name: string;
|
|
501
|
+
/** Job payload */
|
|
502
|
+
payload: any;
|
|
503
|
+
/** Cron expression (null if using interval) */
|
|
504
|
+
cronExpression: string | null;
|
|
505
|
+
/** Interval in milliseconds (null if using cron) */
|
|
506
|
+
everyMs: number | null;
|
|
507
|
+
/** IANA timezone */
|
|
508
|
+
timezone: string;
|
|
509
|
+
/** Start boundary - no jobs dispatched before this */
|
|
510
|
+
from: Date | null;
|
|
511
|
+
/** End boundary - no jobs dispatched after this */
|
|
512
|
+
to: Date | null;
|
|
513
|
+
/** Maximum number of runs */
|
|
514
|
+
limit: number | null;
|
|
515
|
+
/** Number of times this schedule has run */
|
|
516
|
+
runCount: number;
|
|
517
|
+
/** Next scheduled run time */
|
|
518
|
+
nextRunAt: Date | null;
|
|
519
|
+
/** Last run time */
|
|
520
|
+
lastRunAt: Date | null;
|
|
521
|
+
/** Current status */
|
|
522
|
+
status: ScheduleStatus;
|
|
523
|
+
/** When the schedule was created */
|
|
524
|
+
createdAt: Date;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Result returned when creating a schedule.
|
|
528
|
+
*/
|
|
529
|
+
interface ScheduleResult {
|
|
530
|
+
/** Unique identifier for the schedule */
|
|
531
|
+
scheduleId: string;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Options for listing schedules.
|
|
535
|
+
*/
|
|
536
|
+
interface ScheduleListOptions {
|
|
537
|
+
/** Filter by status */
|
|
538
|
+
status?: ScheduleStatus;
|
|
539
|
+
}
|
|
348
540
|
interface QueueManagerConfig {
|
|
349
541
|
default: string;
|
|
350
542
|
adapters: Record<string, AdapterFactory>;
|
|
@@ -357,15 +549,17 @@ interface QueueManagerConfig {
|
|
|
357
549
|
* Custom factory function for job instantiation.
|
|
358
550
|
*
|
|
359
551
|
* Use this to integrate with IoC containers for dependency injection.
|
|
360
|
-
* When provided, this factory is called instead of `new JobClass(
|
|
552
|
+
* When provided, this factory is called instead of `new JobClass()`.
|
|
553
|
+
* The worker will call `$hydrate()` on the returned instance to provide
|
|
554
|
+
* payload, context, and signal.
|
|
361
555
|
*
|
|
362
556
|
* @example
|
|
363
557
|
* ```typescript
|
|
364
558
|
* await QueueManager.init({
|
|
365
559
|
* default: 'redis',
|
|
366
560
|
* adapters: { redis: redis() },
|
|
367
|
-
* jobFactory: async (JobClass
|
|
368
|
-
* return app.container.make(JobClass
|
|
561
|
+
* jobFactory: async (JobClass) => {
|
|
562
|
+
* return app.container.make(JobClass)
|
|
369
563
|
* }
|
|
370
564
|
* })
|
|
371
565
|
* ```
|
|
@@ -504,6 +698,57 @@ interface Adapter {
|
|
|
504
698
|
* Called when the worker stops or the adapter is no longer needed.
|
|
505
699
|
*/
|
|
506
700
|
destroy(): Promise<void>;
|
|
701
|
+
/**
|
|
702
|
+
* Create or update a schedule.
|
|
703
|
+
*
|
|
704
|
+
* If a schedule with the given id exists, it will be updated (upsert).
|
|
705
|
+
* Otherwise, a new schedule is created.
|
|
706
|
+
*
|
|
707
|
+
* @param config - The schedule configuration
|
|
708
|
+
* @returns The schedule ID
|
|
709
|
+
*/
|
|
710
|
+
createSchedule(config: ScheduleConfig): Promise<string>;
|
|
711
|
+
/**
|
|
712
|
+
* Get a schedule by ID.
|
|
713
|
+
*
|
|
714
|
+
* @param id - The schedule ID
|
|
715
|
+
* @returns The schedule data, or null if not found
|
|
716
|
+
*/
|
|
717
|
+
getSchedule(id: string): Promise<ScheduleData | null>;
|
|
718
|
+
/**
|
|
719
|
+
* List all schedules matching the given options.
|
|
720
|
+
*
|
|
721
|
+
* @param options - Optional filters for listing
|
|
722
|
+
* @returns Array of schedule data
|
|
723
|
+
*/
|
|
724
|
+
listSchedules(options?: ScheduleListOptions): Promise<ScheduleData[]>;
|
|
725
|
+
/**
|
|
726
|
+
* Update a schedule's status or run metadata.
|
|
727
|
+
*
|
|
728
|
+
* @param id - The schedule ID
|
|
729
|
+
* @param updates - The fields to update
|
|
730
|
+
*/
|
|
731
|
+
updateSchedule(id: string, updates: Partial<Pick<ScheduleData, 'status' | 'nextRunAt' | 'lastRunAt' | 'runCount'>>): Promise<void>;
|
|
732
|
+
/**
|
|
733
|
+
* Delete a schedule permanently.
|
|
734
|
+
*
|
|
735
|
+
* @param id - The schedule ID to delete
|
|
736
|
+
*/
|
|
737
|
+
deleteSchedule(id: string): Promise<void>;
|
|
738
|
+
/**
|
|
739
|
+
* Atomically claim a due schedule for execution.
|
|
740
|
+
*
|
|
741
|
+
* This method:
|
|
742
|
+
* 1. Finds ONE schedule where nextRunAt <= now AND status = 'active'
|
|
743
|
+
* 2. Calculates and updates its nextRunAt to the next occurrence
|
|
744
|
+
* 3. Increments runCount and sets lastRunAt
|
|
745
|
+
* 4. Returns the schedule data for job dispatching
|
|
746
|
+
*
|
|
747
|
+
* The atomic nature prevents multiple workers from claiming the same schedule.
|
|
748
|
+
*
|
|
749
|
+
* @returns The claimed schedule, or null if no schedules are due
|
|
750
|
+
*/
|
|
751
|
+
claimDueSchedule(): Promise<ScheduleData | null>;
|
|
507
752
|
}
|
|
508
753
|
|
|
509
754
|
/**
|
|
@@ -616,15 +861,15 @@ declare class JobDispatcher<T> {
|
|
|
616
861
|
/**
|
|
617
862
|
* Dispatch the job to the queue.
|
|
618
863
|
*
|
|
619
|
-
* @returns
|
|
864
|
+
* @returns A DispatchResult containing the jobId
|
|
620
865
|
*
|
|
621
866
|
* @example
|
|
622
867
|
* ```typescript
|
|
623
|
-
* const jobId = await SendEmailJob.dispatch(payload).run()
|
|
868
|
+
* const { jobId } = await SendEmailJob.dispatch(payload).run()
|
|
624
869
|
* console.log(`Dispatched job: ${jobId}`)
|
|
625
870
|
* ```
|
|
626
871
|
*/
|
|
627
|
-
run(): Promise
|
|
872
|
+
run(): Promise<DispatchResult>;
|
|
628
873
|
/**
|
|
629
874
|
* Thenable implementation for auto-dispatch when awaited.
|
|
630
875
|
*
|
|
@@ -632,9 +877,80 @@ declare class JobDispatcher<T> {
|
|
|
632
877
|
*
|
|
633
878
|
* @param onFulfilled - Success callback
|
|
634
879
|
* @param onRejected - Error callback
|
|
635
|
-
* @returns Promise resolving to the
|
|
880
|
+
* @returns Promise resolving to the DispatchResult
|
|
881
|
+
*/
|
|
882
|
+
then(onFulfilled?: (value: DispatchResult) => any, onRejected?: (reason: any) => any): Promise<any>;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Fluent builder for creating job schedules.
|
|
887
|
+
*
|
|
888
|
+
* @example
|
|
889
|
+
* ```typescript
|
|
890
|
+
* // Create with cron
|
|
891
|
+
* const { scheduleId } = await new ScheduleBuilder('CleanupJob', { days: 30 })
|
|
892
|
+
* .id('cleanup-daily')
|
|
893
|
+
* .cron('0 0 * * *')
|
|
894
|
+
* .timezone('Europe/Paris')
|
|
895
|
+
* .run()
|
|
896
|
+
*
|
|
897
|
+
* // Create with interval
|
|
898
|
+
* const { scheduleId } = await new ScheduleBuilder('SyncJob', {})
|
|
899
|
+
* .every('5m')
|
|
900
|
+
* .run()
|
|
901
|
+
* ```
|
|
902
|
+
*/
|
|
903
|
+
declare class ScheduleBuilder implements PromiseLike<ScheduleResult> {
|
|
904
|
+
#private;
|
|
905
|
+
constructor(name: string, payload: any);
|
|
906
|
+
/**
|
|
907
|
+
* Set a custom schedule ID.
|
|
908
|
+
* If not specified, defaults to the job name.
|
|
909
|
+
* If a schedule with this ID exists, it will be updated (upsert).
|
|
910
|
+
*/
|
|
911
|
+
id(scheduleId: string): this;
|
|
912
|
+
/**
|
|
913
|
+
* Set a cron expression for the schedule.
|
|
914
|
+
* Mutually exclusive with `every()`.
|
|
915
|
+
*/
|
|
916
|
+
cron(expression: string): this;
|
|
917
|
+
/**
|
|
918
|
+
* Set a repeating interval for the schedule.
|
|
919
|
+
* Mutually exclusive with `cron()`.
|
|
920
|
+
*/
|
|
921
|
+
every(interval: Duration): this;
|
|
922
|
+
/**
|
|
923
|
+
* Set the timezone for cron evaluation.
|
|
924
|
+
* @default 'UTC'
|
|
925
|
+
*/
|
|
926
|
+
timezone(tz: string): this;
|
|
927
|
+
/**
|
|
928
|
+
* Set the start boundary for the schedule.
|
|
929
|
+
* No jobs will be dispatched before this date.
|
|
930
|
+
*/
|
|
931
|
+
from(date: Date): this;
|
|
932
|
+
/**
|
|
933
|
+
* Set the end boundary for the schedule.
|
|
934
|
+
* No jobs will be dispatched after this date.
|
|
935
|
+
*/
|
|
936
|
+
to(date: Date): this;
|
|
937
|
+
/**
|
|
938
|
+
* Set both start and end boundaries for the schedule.
|
|
939
|
+
* Shorthand for `.from(start).to(end)`.
|
|
940
|
+
*/
|
|
941
|
+
between(from: Date, to: Date): this;
|
|
942
|
+
/**
|
|
943
|
+
* Set the maximum number of runs for this schedule.
|
|
944
|
+
*/
|
|
945
|
+
limit(maxRuns: number): this;
|
|
946
|
+
/**
|
|
947
|
+
* Create the schedule and return the schedule ID.
|
|
948
|
+
*/
|
|
949
|
+
run(): Promise<ScheduleResult>;
|
|
950
|
+
/**
|
|
951
|
+
* Implement PromiseLike to allow `await builder.every('5m')` syntax.
|
|
636
952
|
*/
|
|
637
|
-
then(
|
|
953
|
+
then<TResult1 = ScheduleResult, TResult2 = never>(onfulfilled?: ((value: ScheduleResult) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
638
954
|
}
|
|
639
955
|
|
|
640
956
|
/**
|
|
@@ -643,12 +959,14 @@ declare class JobDispatcher<T> {
|
|
|
643
959
|
* Extend this class to create your own jobs. Each job must implement
|
|
644
960
|
* the `execute()` method which contains the job's business logic.
|
|
645
961
|
*
|
|
962
|
+
* The constructor is reserved for dependency injection. Payload and context
|
|
963
|
+
* are provided separately via the `$hydrate()` method (called by the worker).
|
|
964
|
+
*
|
|
646
965
|
* @typeParam Payload - The type of data this job receives
|
|
647
966
|
*
|
|
648
967
|
* @example
|
|
649
968
|
* ```typescript
|
|
650
969
|
* import { Job } from '@boringnode/queue'
|
|
651
|
-
* import type { JobContext } from '@boringnode/queue'
|
|
652
970
|
*
|
|
653
971
|
* interface SendEmailPayload {
|
|
654
972
|
* to: string
|
|
@@ -662,13 +980,14 @@ declare class JobDispatcher<T> {
|
|
|
662
980
|
* maxRetries: 3,
|
|
663
981
|
* }
|
|
664
982
|
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
983
|
+
* // Constructor is for dependency injection only
|
|
984
|
+
* constructor(private mailer: MailerService) {
|
|
985
|
+
* super()
|
|
667
986
|
* }
|
|
668
987
|
*
|
|
669
988
|
* async execute() {
|
|
670
989
|
* console.log(`Attempt ${this.context.attempt} for job ${this.context.jobId}`)
|
|
671
|
-
* await
|
|
990
|
+
* await this.mailer.send(this.payload.to, this.payload.subject, this.payload.body)
|
|
672
991
|
* }
|
|
673
992
|
*
|
|
674
993
|
* async failed(error: Error) {
|
|
@@ -679,9 +998,38 @@ declare class JobDispatcher<T> {
|
|
|
679
998
|
*/
|
|
680
999
|
declare abstract class Job<Payload = any> {
|
|
681
1000
|
#private;
|
|
682
|
-
/**
|
|
1001
|
+
/**
|
|
1002
|
+
* Static options for this job class.
|
|
1003
|
+
*
|
|
1004
|
+
* Override this property in subclasses to configure job behavior
|
|
1005
|
+
* such as queue name, retry policy, timeout, and more.
|
|
1006
|
+
*
|
|
1007
|
+
* @example
|
|
1008
|
+
* ```typescript
|
|
1009
|
+
* class SendEmailJob extends Job<SendEmailPayload> {
|
|
1010
|
+
* static options = {
|
|
1011
|
+
* queue: 'emails',
|
|
1012
|
+
* maxRetries: 3,
|
|
1013
|
+
* timeout: '30s',
|
|
1014
|
+
* }
|
|
1015
|
+
* }
|
|
1016
|
+
* ```
|
|
1017
|
+
*/
|
|
683
1018
|
static options: JobOptions;
|
|
684
|
-
/**
|
|
1019
|
+
/**
|
|
1020
|
+
* The payload data passed to this job instance.
|
|
1021
|
+
*
|
|
1022
|
+
* Contains the data provided when the job was dispatched.
|
|
1023
|
+
* Available after the job has been hydrated by the worker.
|
|
1024
|
+
*
|
|
1025
|
+
* @example
|
|
1026
|
+
* ```typescript
|
|
1027
|
+
* async execute() {
|
|
1028
|
+
* const { to, subject, body } = this.payload
|
|
1029
|
+
* await sendEmail(to, subject, body)
|
|
1030
|
+
* }
|
|
1031
|
+
* ```
|
|
1032
|
+
*/
|
|
685
1033
|
get payload(): Payload;
|
|
686
1034
|
/**
|
|
687
1035
|
* Context information for the current job execution.
|
|
@@ -701,12 +1049,36 @@ declare abstract class Job<Payload = any> {
|
|
|
701
1049
|
*/
|
|
702
1050
|
get context(): JobContext;
|
|
703
1051
|
/**
|
|
704
|
-
*
|
|
1052
|
+
* The abort signal for timeout handling.
|
|
1053
|
+
*
|
|
1054
|
+
* Check `signal.aborted` in long-running operations to handle timeouts gracefully.
|
|
1055
|
+
*
|
|
1056
|
+
* @example
|
|
1057
|
+
* ```typescript
|
|
1058
|
+
* async execute() {
|
|
1059
|
+
* for (const item of this.payload.items) {
|
|
1060
|
+
* if (this.signal?.aborted) {
|
|
1061
|
+
* throw new Error('Job timed out')
|
|
1062
|
+
* }
|
|
1063
|
+
* await processItem(item)
|
|
1064
|
+
* }
|
|
1065
|
+
* }
|
|
1066
|
+
* ```
|
|
1067
|
+
*/
|
|
1068
|
+
get signal(): AbortSignal | undefined;
|
|
1069
|
+
/**
|
|
1070
|
+
* Hydrate the job with payload, context, and optional abort signal.
|
|
1071
|
+
*
|
|
1072
|
+
* This method is called by the worker after instantiation to provide
|
|
1073
|
+
* the job's runtime data. It should not be called directly by user code.
|
|
705
1074
|
*
|
|
706
1075
|
* @param payload - The data to be processed by this job
|
|
707
|
-
* @param context - The job execution context
|
|
1076
|
+
* @param context - The job execution context
|
|
1077
|
+
* @param signal - Optional abort signal for timeout handling
|
|
1078
|
+
*
|
|
1079
|
+
* @internal
|
|
708
1080
|
*/
|
|
709
|
-
|
|
1081
|
+
$hydrate(payload: Payload, context: JobContext, signal?: AbortSignal): void;
|
|
710
1082
|
/**
|
|
711
1083
|
* Dispatch this job to the queue.
|
|
712
1084
|
*
|
|
@@ -730,22 +1102,48 @@ declare abstract class Job<Payload = any> {
|
|
|
730
1102
|
* .run()
|
|
731
1103
|
* ```
|
|
732
1104
|
*/
|
|
733
|
-
static dispatch<T extends Job>(this: new (
|
|
1105
|
+
static dispatch<T extends Job>(this: new (...args: any[]) => T, payload: T extends Job<infer P> ? P : never): JobDispatcher<T extends Job<infer P> ? P : never>;
|
|
1106
|
+
/**
|
|
1107
|
+
* Create a schedule for this job.
|
|
1108
|
+
*
|
|
1109
|
+
* Returns a ScheduleBuilder for fluent configuration before creating the schedule.
|
|
1110
|
+
* The schedule is not actually created until `.run()` is called or the
|
|
1111
|
+
* builder is awaited.
|
|
1112
|
+
*
|
|
1113
|
+
* @param payload - The data to pass to the job on each run
|
|
1114
|
+
* @returns A ScheduleBuilder for fluent configuration
|
|
1115
|
+
*
|
|
1116
|
+
* @example
|
|
1117
|
+
* ```typescript
|
|
1118
|
+
* // Cron schedule
|
|
1119
|
+
* await CleanupJob.schedule({ days: 30 })
|
|
1120
|
+
* .id('cleanup-daily')
|
|
1121
|
+
* .cron('0 0 * * *')
|
|
1122
|
+
* .timezone('Europe/Paris')
|
|
1123
|
+
* .run()
|
|
1124
|
+
*
|
|
1125
|
+
* // Interval schedule
|
|
1126
|
+
* await SyncJob.schedule({ source: 'api' })
|
|
1127
|
+
* .every('5m')
|
|
1128
|
+
* .run()
|
|
1129
|
+
* ```
|
|
1130
|
+
*/
|
|
1131
|
+
static schedule<T extends Job>(this: new (...args: any[]) => T, payload: T extends Job<infer P> ? P : never): ScheduleBuilder;
|
|
734
1132
|
/**
|
|
735
1133
|
* Execute the job's business logic.
|
|
736
1134
|
*
|
|
737
1135
|
* This method is called by the worker when processing the job.
|
|
738
1136
|
* Implement your job's logic here.
|
|
739
1137
|
*
|
|
740
|
-
*
|
|
741
|
-
*
|
|
1138
|
+
* For timeout handling, use `this.signal` which is available after hydration.
|
|
1139
|
+
*
|
|
742
1140
|
* @throws Any error thrown will trigger retry logic (if configured)
|
|
743
1141
|
*
|
|
744
1142
|
* @example
|
|
745
1143
|
* ```typescript
|
|
746
|
-
* async execute(
|
|
1144
|
+
* async execute() {
|
|
747
1145
|
* for (const item of this.payload.items) {
|
|
748
|
-
* if (signal?.aborted) {
|
|
1146
|
+
* if (this.signal?.aborted) {
|
|
749
1147
|
* throw new Error('Job timed out')
|
|
750
1148
|
* }
|
|
751
1149
|
* await processItem(item)
|
|
@@ -753,7 +1151,7 @@ declare abstract class Job<Payload = any> {
|
|
|
753
1151
|
* }
|
|
754
1152
|
* ```
|
|
755
1153
|
*/
|
|
756
|
-
abstract execute(
|
|
1154
|
+
abstract execute(): Promise<void>;
|
|
757
1155
|
/**
|
|
758
1156
|
* Called when the job has permanently failed (after all retries exhausted).
|
|
759
1157
|
*
|
|
@@ -773,4 +1171,4 @@ declare abstract class Job<Payload = any> {
|
|
|
773
1171
|
failed?(error: Error): Promise<void>;
|
|
774
1172
|
}
|
|
775
1173
|
|
|
776
|
-
export { type Adapter as A, type BackoffStrategy as B, type Duration as D, type JobData as J, type Logger as L, type QueueManagerConfig as Q, type RetryConfig as R, type WorkerCycle as W, type AcquiredJob as a, type
|
|
1174
|
+
export { type Adapter as A, type BackoffStrategy as B, type Duration as D, type JobData as J, type Logger as L, type QueueManagerConfig as Q, type RetryConfig as R, type ScheduleConfig as S, type WorkerCycle as W, type AcquiredJob as a, type ScheduleData as b, type ScheduleListOptions as c, type JobFactory as d, Job as e, type JobClass as f, type ScheduleStatus as g, ScheduleBuilder as h, customBackoff as i, exponentialBackoff as j, fixedBackoff as k, linearBackoff as l, type DispatchResult as m, type JobOptions as n, type JobContext as o, type BackoffConfig as p, type QueueConfig as q, type WorkerConfig as r, type AdapterFactory as s, type ScheduleResult as t };
|