@boringnode/queue 0.1.0 → 0.3.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 +230 -358
- package/build/{chunk-US7THLSZ.js → chunk-LI2ZMCNO.js} +17 -3
- package/build/chunk-LI2ZMCNO.js.map +1 -0
- package/build/{chunk-NPQKBCCY.js → chunk-PBGPIFI5.js} +15 -1
- package/build/chunk-PBGPIFI5.js.map +1 -0
- package/build/{index-2Ng_OpVK.d.ts → index-PDfE6h8d.d.ts} +454 -36
- package/build/index.d.ts +8 -4
- package/build/index.js +313 -46
- package/build/index.js.map +1 -1
- package/build/src/contracts/adapter.d.ts +1 -1
- package/build/src/drivers/knex_adapter.d.ts +6 -3
- package/build/src/drivers/knex_adapter.js +94 -12
- package/build/src/drivers/knex_adapter.js.map +1 -1
- package/build/src/drivers/redis_adapter.d.ts +6 -3
- package/build/src/drivers/redis_adapter.js +337 -96
- package/build/src/drivers/redis_adapter.js.map +1 -1
- package/build/src/drivers/sync_adapter.d.ts +6 -3
- package/build/src/drivers/sync_adapter.js +18 -6
- 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-NPQKBCCY.js.map +0 -1
- package/build/chunk-US7THLSZ.js.map +0 -1
|
@@ -185,7 +185,34 @@ 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
|
+
* Retention policy for completed/failed jobs.
|
|
203
|
+
*
|
|
204
|
+
* - `true` (default): Remove job immediately
|
|
205
|
+
* - `false`: Keep job in history indefinitely
|
|
206
|
+
* - `{ age?, count? }`: Keep with pruning by age and/or count
|
|
207
|
+
*/
|
|
208
|
+
type JobRetention = boolean | {
|
|
209
|
+
age?: Duration;
|
|
210
|
+
count?: number;
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Possible statuses for a job in the queue.
|
|
214
|
+
*/
|
|
215
|
+
type JobStatus = 'pending' | 'active' | 'delayed' | 'completed' | 'failed';
|
|
189
216
|
/**
|
|
190
217
|
* Result returned when dispatching a job.
|
|
191
218
|
*
|
|
@@ -199,23 +226,152 @@ interface DispatchResult {
|
|
|
199
226
|
/** Unique identifier for this specific job instance */
|
|
200
227
|
jobId: string;
|
|
201
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Result returned when dispatching multiple jobs at once.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* const { jobIds } = await SendEmailJob.dispatchMany(payloads)
|
|
235
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
interface DispatchManyResult {
|
|
239
|
+
/** Unique identifiers for all dispatched job instances */
|
|
240
|
+
jobIds: string[];
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Internal representation of a job in the queue.
|
|
244
|
+
*
|
|
245
|
+
* This is used by adapters to store and retrieve job data.
|
|
246
|
+
* Not typically used directly by application code.
|
|
247
|
+
*/
|
|
202
248
|
interface JobData {
|
|
249
|
+
/**
|
|
250
|
+
* Unique identifier for this job.
|
|
251
|
+
*/
|
|
203
252
|
id: string;
|
|
253
|
+
/**
|
|
254
|
+
* Job class name.
|
|
255
|
+
*/
|
|
204
256
|
name: string;
|
|
257
|
+
/**
|
|
258
|
+
* Serialized job payload.
|
|
259
|
+
*/
|
|
205
260
|
payload: any;
|
|
261
|
+
/**
|
|
262
|
+
* Number of execution attempts so far.
|
|
263
|
+
*/
|
|
206
264
|
attempts: number;
|
|
265
|
+
/**
|
|
266
|
+
* Job priority (lower = higher priority).
|
|
267
|
+
*
|
|
268
|
+
* @default 0
|
|
269
|
+
*/
|
|
207
270
|
priority?: number;
|
|
271
|
+
/**
|
|
272
|
+
* When to retry this job next (for failed jobs).
|
|
273
|
+
*/
|
|
208
274
|
nextRetryAt?: Date;
|
|
275
|
+
/**
|
|
276
|
+
* Number of times this job was recovered from stalled state.
|
|
277
|
+
*/
|
|
209
278
|
stalledCount?: number;
|
|
279
|
+
/**
|
|
280
|
+
* Optional group identifier for organizing related jobs.
|
|
281
|
+
*
|
|
282
|
+
* Jobs with the same groupId can be filtered and displayed together
|
|
283
|
+
* in monitoring UIs. Useful for batch operations like newsletters
|
|
284
|
+
* or bulk exports.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* await SendEmailJob.dispatch({ to: 'user@example.com' })
|
|
289
|
+
* .group('newsletter-jan-2025')
|
|
290
|
+
* .run()
|
|
291
|
+
* ```
|
|
292
|
+
*/
|
|
293
|
+
groupId?: string;
|
|
210
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Record of a job's current state, including history for completed/failed jobs.
|
|
297
|
+
*/
|
|
298
|
+
interface JobRecord {
|
|
299
|
+
/** Current status of the job */
|
|
300
|
+
status: JobStatus;
|
|
301
|
+
/** Original job data */
|
|
302
|
+
data: JobData;
|
|
303
|
+
/** Timestamp when the job finished (for completed/failed jobs) */
|
|
304
|
+
finishedAt?: number;
|
|
305
|
+
/** Error message (for failed jobs) */
|
|
306
|
+
error?: string;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Static options for a Job class.
|
|
310
|
+
*
|
|
311
|
+
* Define these as a static property on your Job class to configure
|
|
312
|
+
* default behavior for all instances.
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* ```typescript
|
|
316
|
+
* class SendEmailJob extends Job<EmailPayload> {
|
|
317
|
+
* static options: JobOptions = {
|
|
318
|
+
* name: 'SendEmailJob',
|
|
319
|
+
* queue: 'emails',
|
|
320
|
+
* maxRetries: 3,
|
|
321
|
+
* timeout: '30s',
|
|
322
|
+
* }
|
|
323
|
+
* }
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
211
326
|
interface JobOptions {
|
|
327
|
+
/**
|
|
328
|
+
* Unique name for this job class.
|
|
329
|
+
*
|
|
330
|
+
* Used to identify the job when dispatching and processing.
|
|
331
|
+
*
|
|
332
|
+
* @default constructor.name
|
|
333
|
+
*/
|
|
334
|
+
name?: string;
|
|
335
|
+
/**
|
|
336
|
+
* Queue name for this job.
|
|
337
|
+
*
|
|
338
|
+
* @default 'default'
|
|
339
|
+
*/
|
|
212
340
|
queue?: string;
|
|
341
|
+
/**
|
|
342
|
+
* Adapter name or factory to use for this job.
|
|
343
|
+
*/
|
|
213
344
|
adapter?: string | (() => Adapter);
|
|
345
|
+
/**
|
|
346
|
+
* Maximum retry attempts before permanent failure.
|
|
347
|
+
*
|
|
348
|
+
* @default 3
|
|
349
|
+
*/
|
|
214
350
|
maxRetries?: number;
|
|
351
|
+
/**
|
|
352
|
+
* Job priority (lower = higher priority).
|
|
353
|
+
*
|
|
354
|
+
* @default 0
|
|
355
|
+
*/
|
|
215
356
|
priority?: number;
|
|
357
|
+
/**
|
|
358
|
+
* Retry configuration (backoff strategy, delays, etc.).
|
|
359
|
+
*/
|
|
216
360
|
retry?: RetryConfig;
|
|
361
|
+
/**
|
|
362
|
+
* Maximum execution time before timeout.
|
|
363
|
+
*
|
|
364
|
+
* @default undefined (no timeout)
|
|
365
|
+
*/
|
|
217
366
|
timeout?: Duration;
|
|
367
|
+
/**
|
|
368
|
+
* Whether to mark job as failed on timeout.
|
|
369
|
+
*
|
|
370
|
+
* @default true
|
|
371
|
+
*/
|
|
218
372
|
failOnTimeout?: boolean;
|
|
373
|
+
removeOnComplete?: JobRetention;
|
|
374
|
+
removeOnFail?: JobRetention;
|
|
219
375
|
}
|
|
220
376
|
/**
|
|
221
377
|
* Context information available to a job during execution.
|
|
@@ -249,34 +405,39 @@ interface JobContext {
|
|
|
249
405
|
/** Number of times this job has been recovered from stalled state */
|
|
250
406
|
stalledCount: number;
|
|
251
407
|
}
|
|
252
|
-
|
|
408
|
+
/**
|
|
409
|
+
* Type representing a Job class constructor.
|
|
410
|
+
*
|
|
411
|
+
* The constructor accepts any arguments for dependency injection.
|
|
412
|
+
* Payload and context are provided separately via `$hydrate()`.
|
|
413
|
+
*/
|
|
414
|
+
type JobClass<T extends Job = Job> = (new (...args: any[]) => T) & {
|
|
253
415
|
options?: JobOptions;
|
|
254
416
|
};
|
|
255
417
|
/**
|
|
256
418
|
* Factory function for custom job instantiation.
|
|
257
419
|
*
|
|
258
420
|
* Use this to integrate with IoC containers for dependency injection.
|
|
259
|
-
* The factory receives the job class
|
|
260
|
-
*
|
|
421
|
+
* The factory receives only the job class and should return an instance
|
|
422
|
+
* with all dependencies injected. The worker will call `$hydrate()` separately
|
|
423
|
+
* to provide payload, context, and signal.
|
|
261
424
|
*
|
|
262
425
|
* @param JobClass - The job class to instantiate
|
|
263
|
-
* @param payload - The payload data for the job
|
|
264
|
-
* @param context - The job execution context (jobId, attempt, queue, etc.)
|
|
265
426
|
* @returns The job instance, or a Promise resolving to the instance
|
|
266
427
|
*
|
|
267
428
|
* @example
|
|
268
429
|
* ```typescript
|
|
269
430
|
* // With AdonisJS IoC container
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
431
|
+
* await QueueManager.init({
|
|
432
|
+
* default: 'redis',
|
|
433
|
+
* adapters: { redis: redis() },
|
|
434
|
+
* jobFactory: async (JobClass) => {
|
|
435
|
+
* return app.container.make(JobClass)
|
|
275
436
|
* }
|
|
276
437
|
* })
|
|
277
438
|
* ```
|
|
278
439
|
*/
|
|
279
|
-
type JobFactory = (JobClass: JobClass
|
|
440
|
+
type JobFactory = (JobClass: JobClass) => Job | Promise<Job>;
|
|
280
441
|
interface RetryConfig {
|
|
281
442
|
maxRetries?: number;
|
|
282
443
|
backoff?: () => BackoffStrategy$1;
|
|
@@ -292,6 +453,7 @@ interface BackoffConfig {
|
|
|
292
453
|
interface QueueConfig {
|
|
293
454
|
adapter?: string;
|
|
294
455
|
retry?: any;
|
|
456
|
+
defaultJobOptions?: JobOptions;
|
|
295
457
|
}
|
|
296
458
|
interface WorkerConfig {
|
|
297
459
|
/**
|
|
@@ -370,7 +532,7 @@ interface ScheduleConfig {
|
|
|
370
532
|
/** Optional ID for the schedule (UUID if not set). Used for upsert. */
|
|
371
533
|
id?: string;
|
|
372
534
|
/** Job class name */
|
|
373
|
-
|
|
535
|
+
name: string;
|
|
374
536
|
/** Job payload */
|
|
375
537
|
payload: any;
|
|
376
538
|
/** Cron expression (mutually exclusive with everyMs) */
|
|
@@ -394,7 +556,7 @@ interface ScheduleData {
|
|
|
394
556
|
/** Unique identifier */
|
|
395
557
|
id: string;
|
|
396
558
|
/** Job class name */
|
|
397
|
-
|
|
559
|
+
name: string;
|
|
398
560
|
/** Job payload */
|
|
399
561
|
payload: any;
|
|
400
562
|
/** Cron expression (null if using interval) */
|
|
@@ -438,6 +600,7 @@ interface QueueManagerConfig {
|
|
|
438
600
|
default: string;
|
|
439
601
|
adapters: Record<string, AdapterFactory>;
|
|
440
602
|
retry?: RetryConfig;
|
|
603
|
+
defaultJobOptions?: JobOptions;
|
|
441
604
|
queues?: Record<string, QueueConfig>;
|
|
442
605
|
worker?: WorkerConfig;
|
|
443
606
|
locations?: string[];
|
|
@@ -446,15 +609,17 @@ interface QueueManagerConfig {
|
|
|
446
609
|
* Custom factory function for job instantiation.
|
|
447
610
|
*
|
|
448
611
|
* Use this to integrate with IoC containers for dependency injection.
|
|
449
|
-
* When provided, this factory is called instead of `new JobClass(
|
|
612
|
+
* When provided, this factory is called instead of `new JobClass()`.
|
|
613
|
+
* The worker will call `$hydrate()` on the returned instance to provide
|
|
614
|
+
* payload, context, and signal.
|
|
450
615
|
*
|
|
451
616
|
* @example
|
|
452
617
|
* ```typescript
|
|
453
618
|
* await QueueManager.init({
|
|
454
619
|
* default: 'redis',
|
|
455
620
|
* adapters: { redis: redis() },
|
|
456
|
-
* jobFactory: async (JobClass
|
|
457
|
-
* return app.container.make(JobClass
|
|
621
|
+
* jobFactory: async (JobClass) => {
|
|
622
|
+
* return app.container.make(JobClass)
|
|
458
623
|
* }
|
|
459
624
|
* })
|
|
460
625
|
* ```
|
|
@@ -529,16 +694,18 @@ interface Adapter {
|
|
|
529
694
|
*
|
|
530
695
|
* @param jobId - The job ID to complete
|
|
531
696
|
* @param queue - The queue the job belongs to
|
|
697
|
+
* @param removeOnComplete - Optional retention policy for completed jobs
|
|
532
698
|
*/
|
|
533
|
-
completeJob(jobId: string, queue: string): Promise<void>;
|
|
699
|
+
completeJob(jobId: string, queue: string, removeOnComplete?: JobRetention): Promise<void>;
|
|
534
700
|
/**
|
|
535
701
|
* Mark a job as failed permanently and remove it from the queue.
|
|
536
702
|
*
|
|
537
703
|
* @param jobId - The job ID to fail
|
|
538
704
|
* @param queue - The queue the job belongs to
|
|
539
705
|
* @param error - Optional error that caused the failure
|
|
706
|
+
* @param removeOnFail - Optional retention policy for failed jobs
|
|
540
707
|
*/
|
|
541
|
-
failJob(jobId: string, queue: string, error?: Error): Promise<void>;
|
|
708
|
+
failJob(jobId: string, queue: string, error?: Error, removeOnFail?: JobRetention): Promise<void>;
|
|
542
709
|
/**
|
|
543
710
|
* Retry a job by moving it back to pending with incremented attempts.
|
|
544
711
|
*
|
|
@@ -547,6 +714,14 @@ interface Adapter {
|
|
|
547
714
|
* @param retryAt - Optional future date to delay the retry
|
|
548
715
|
*/
|
|
549
716
|
retryJob(jobId: string, queue: string, retryAt?: Date): Promise<void>;
|
|
717
|
+
/**
|
|
718
|
+
* Get a job record by id.
|
|
719
|
+
*
|
|
720
|
+
* @param jobId - The job ID to retrieve
|
|
721
|
+
* @param queue - The queue the job belongs to
|
|
722
|
+
* @returns The job record, or null if not found
|
|
723
|
+
*/
|
|
724
|
+
getJob(jobId: string, queue: string): Promise<JobRecord | null>;
|
|
550
725
|
/**
|
|
551
726
|
* Push a job to the default queue for immediate processing.
|
|
552
727
|
*
|
|
@@ -575,6 +750,25 @@ interface Adapter {
|
|
|
575
750
|
* @param delay - Delay in milliseconds before the job becomes available
|
|
576
751
|
*/
|
|
577
752
|
pushLaterOn(queue: string, jobData: JobData, delay: number): Promise<void>;
|
|
753
|
+
/**
|
|
754
|
+
* Push multiple jobs to the default queue for immediate processing.
|
|
755
|
+
*
|
|
756
|
+
* This is more efficient than calling push() multiple times as it
|
|
757
|
+
* batches the operations (e.g., Redis pipeline, SQL batch insert).
|
|
758
|
+
*
|
|
759
|
+
* @param jobs - Array of job data to push
|
|
760
|
+
*/
|
|
761
|
+
pushMany(jobs: JobData[]): Promise<void>;
|
|
762
|
+
/**
|
|
763
|
+
* Push multiple jobs to a specific queue for immediate processing.
|
|
764
|
+
*
|
|
765
|
+
* This is more efficient than calling pushOn() multiple times as it
|
|
766
|
+
* batches the operations (e.g., Redis pipeline, SQL batch insert).
|
|
767
|
+
*
|
|
768
|
+
* @param queue - The queue name to push to
|
|
769
|
+
* @param jobs - Array of job data to push
|
|
770
|
+
*/
|
|
771
|
+
pushManyOn(queue: string, jobs: JobData[]): Promise<void>;
|
|
578
772
|
/**
|
|
579
773
|
* Get the number of pending jobs in the default queue.
|
|
580
774
|
*
|
|
@@ -737,6 +931,25 @@ declare class JobDispatcher<T> {
|
|
|
737
931
|
* ```
|
|
738
932
|
*/
|
|
739
933
|
priority(priority: number): this;
|
|
934
|
+
/**
|
|
935
|
+
* Assign this job to a group.
|
|
936
|
+
*
|
|
937
|
+
* Jobs with the same groupId can be filtered and displayed together
|
|
938
|
+
* in monitoring UIs. Useful for batch operations like newsletters
|
|
939
|
+
* or bulk exports.
|
|
940
|
+
*
|
|
941
|
+
* @param groupId - Group identifier
|
|
942
|
+
* @returns This dispatcher for chaining
|
|
943
|
+
*
|
|
944
|
+
* @example
|
|
945
|
+
* ```typescript
|
|
946
|
+
* // Group newsletter jobs together
|
|
947
|
+
* await SendEmailJob.dispatch({ to: 'user@example.com' })
|
|
948
|
+
* .group('newsletter-jan-2025')
|
|
949
|
+
* .run()
|
|
950
|
+
* ```
|
|
951
|
+
*/
|
|
952
|
+
group(groupId: string): this;
|
|
740
953
|
/**
|
|
741
954
|
* Use a specific adapter for this job.
|
|
742
955
|
*
|
|
@@ -777,6 +990,127 @@ declare class JobDispatcher<T> {
|
|
|
777
990
|
then(onFulfilled?: (value: DispatchResult) => any, onRejected?: (reason: any) => any): Promise<any>;
|
|
778
991
|
}
|
|
779
992
|
|
|
993
|
+
/**
|
|
994
|
+
* Fluent builder for dispatching multiple jobs to the queue in a single batch.
|
|
995
|
+
*
|
|
996
|
+
* Provides a chainable API for configuring job options before dispatch.
|
|
997
|
+
* Usually created via `Job.dispatchMany()` rather than directly.
|
|
998
|
+
*
|
|
999
|
+
* ```
|
|
1000
|
+
* Job.dispatchMany(payloads)
|
|
1001
|
+
* .toQueue('emails') // optional: target queue
|
|
1002
|
+
* .priority(1) // optional: 1-10, lower = higher priority
|
|
1003
|
+
* .group('batch-123') // optional: group all jobs together
|
|
1004
|
+
* .with('redis') // optional: specific adapter
|
|
1005
|
+
* .run() // dispatch all jobs
|
|
1006
|
+
* ```
|
|
1007
|
+
*
|
|
1008
|
+
* @typeParam T - The payload type for these jobs
|
|
1009
|
+
*
|
|
1010
|
+
* @example
|
|
1011
|
+
* ```typescript
|
|
1012
|
+
* // Batch dispatch for newsletter
|
|
1013
|
+
* const { jobIds } = await SendEmailJob.dispatchMany([
|
|
1014
|
+
* { to: 'user1@example.com', subject: 'Newsletter' },
|
|
1015
|
+
* { to: 'user2@example.com', subject: 'Newsletter' },
|
|
1016
|
+
* ])
|
|
1017
|
+
* .group('newsletter-jan-2025')
|
|
1018
|
+
* .toQueue('emails')
|
|
1019
|
+
* .run()
|
|
1020
|
+
*
|
|
1021
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
1022
|
+
* ```
|
|
1023
|
+
*/
|
|
1024
|
+
declare class JobBatchDispatcher<T> {
|
|
1025
|
+
#private;
|
|
1026
|
+
/**
|
|
1027
|
+
* Create a new batch job dispatcher.
|
|
1028
|
+
*
|
|
1029
|
+
* @param name - The job class name (used to locate the class at runtime)
|
|
1030
|
+
* @param payloads - Array of data to pass to each job
|
|
1031
|
+
*/
|
|
1032
|
+
constructor(name: string, payloads: T[]);
|
|
1033
|
+
/**
|
|
1034
|
+
* Set the target queue for all jobs.
|
|
1035
|
+
*
|
|
1036
|
+
* @param queue - Queue name (default: 'default')
|
|
1037
|
+
* @returns This dispatcher for chaining
|
|
1038
|
+
*
|
|
1039
|
+
* @example
|
|
1040
|
+
* ```typescript
|
|
1041
|
+
* await SendEmailJob.dispatchMany(payloads).toQueue('emails')
|
|
1042
|
+
* ```
|
|
1043
|
+
*/
|
|
1044
|
+
toQueue(queue: string): this;
|
|
1045
|
+
/**
|
|
1046
|
+
* Set the priority for all jobs.
|
|
1047
|
+
*
|
|
1048
|
+
* Lower numbers = higher priority. Jobs with lower priority values
|
|
1049
|
+
* are processed before jobs with higher values.
|
|
1050
|
+
*
|
|
1051
|
+
* @param priority - Priority level (1-10, default: 5)
|
|
1052
|
+
* @returns This dispatcher for chaining
|
|
1053
|
+
*
|
|
1054
|
+
* @example
|
|
1055
|
+
* ```typescript
|
|
1056
|
+
* await UrgentJob.dispatchMany(payloads).priority(1)
|
|
1057
|
+
* ```
|
|
1058
|
+
*/
|
|
1059
|
+
priority(priority: number): this;
|
|
1060
|
+
/**
|
|
1061
|
+
* Assign all jobs to a group.
|
|
1062
|
+
*
|
|
1063
|
+
* Jobs with the same groupId can be filtered and displayed together
|
|
1064
|
+
* in monitoring UIs. Useful for batch operations like newsletters
|
|
1065
|
+
* or bulk exports.
|
|
1066
|
+
*
|
|
1067
|
+
* @param groupId - Group identifier
|
|
1068
|
+
* @returns This dispatcher for chaining
|
|
1069
|
+
*
|
|
1070
|
+
* @example
|
|
1071
|
+
* ```typescript
|
|
1072
|
+
* await SendEmailJob.dispatchMany(recipients)
|
|
1073
|
+
* .group('newsletter-jan-2025')
|
|
1074
|
+
* .run()
|
|
1075
|
+
* ```
|
|
1076
|
+
*/
|
|
1077
|
+
group(groupId: string): this;
|
|
1078
|
+
/**
|
|
1079
|
+
* Use a specific adapter for these jobs.
|
|
1080
|
+
*
|
|
1081
|
+
* @param adapter - Adapter name or factory function
|
|
1082
|
+
* @returns This dispatcher for chaining
|
|
1083
|
+
*
|
|
1084
|
+
* @example
|
|
1085
|
+
* ```typescript
|
|
1086
|
+
* await Job.dispatchMany(payloads).with('redis')
|
|
1087
|
+
* ```
|
|
1088
|
+
*/
|
|
1089
|
+
with(adapter: string | (() => Adapter)): this;
|
|
1090
|
+
/**
|
|
1091
|
+
* Dispatch all jobs to the queue.
|
|
1092
|
+
*
|
|
1093
|
+
* @returns A DispatchManyResult containing all jobIds
|
|
1094
|
+
*
|
|
1095
|
+
* @example
|
|
1096
|
+
* ```typescript
|
|
1097
|
+
* const { jobIds } = await SendEmailJob.dispatchMany(payloads).run()
|
|
1098
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
1099
|
+
* ```
|
|
1100
|
+
*/
|
|
1101
|
+
run(): Promise<DispatchManyResult>;
|
|
1102
|
+
/**
|
|
1103
|
+
* Thenable implementation for auto-dispatch when awaited.
|
|
1104
|
+
*
|
|
1105
|
+
* Allows `await Job.dispatchMany(payloads)` without explicit `.run()`.
|
|
1106
|
+
*
|
|
1107
|
+
* @param onFulfilled - Success callback
|
|
1108
|
+
* @param onRejected - Error callback
|
|
1109
|
+
* @returns Promise resolving to the DispatchManyResult
|
|
1110
|
+
*/
|
|
1111
|
+
then(onFulfilled?: (value: DispatchManyResult) => any, onRejected?: (reason: any) => any): Promise<any>;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
780
1114
|
/**
|
|
781
1115
|
* Fluent builder for creating job schedules.
|
|
782
1116
|
*
|
|
@@ -797,7 +1131,7 @@ declare class JobDispatcher<T> {
|
|
|
797
1131
|
*/
|
|
798
1132
|
declare class ScheduleBuilder implements PromiseLike<ScheduleResult> {
|
|
799
1133
|
#private;
|
|
800
|
-
constructor(
|
|
1134
|
+
constructor(name: string, payload: any);
|
|
801
1135
|
/**
|
|
802
1136
|
* Set a custom schedule ID.
|
|
803
1137
|
* If not specified, defaults to the job name.
|
|
@@ -854,12 +1188,14 @@ declare class ScheduleBuilder implements PromiseLike<ScheduleResult> {
|
|
|
854
1188
|
* Extend this class to create your own jobs. Each job must implement
|
|
855
1189
|
* the `execute()` method which contains the job's business logic.
|
|
856
1190
|
*
|
|
1191
|
+
* The constructor is reserved for dependency injection. Payload and context
|
|
1192
|
+
* are provided separately via the `$hydrate()` method (called by the worker).
|
|
1193
|
+
*
|
|
857
1194
|
* @typeParam Payload - The type of data this job receives
|
|
858
1195
|
*
|
|
859
1196
|
* @example
|
|
860
1197
|
* ```typescript
|
|
861
1198
|
* import { Job } from '@boringnode/queue'
|
|
862
|
-
* import type { JobContext } from '@boringnode/queue'
|
|
863
1199
|
*
|
|
864
1200
|
* interface SendEmailPayload {
|
|
865
1201
|
* to: string
|
|
@@ -873,13 +1209,14 @@ declare class ScheduleBuilder implements PromiseLike<ScheduleResult> {
|
|
|
873
1209
|
* maxRetries: 3,
|
|
874
1210
|
* }
|
|
875
1211
|
*
|
|
876
|
-
*
|
|
877
|
-
*
|
|
1212
|
+
* // Constructor is for dependency injection only
|
|
1213
|
+
* constructor(private mailer: MailerService) {
|
|
1214
|
+
* super()
|
|
878
1215
|
* }
|
|
879
1216
|
*
|
|
880
1217
|
* async execute() {
|
|
881
1218
|
* console.log(`Attempt ${this.context.attempt} for job ${this.context.jobId}`)
|
|
882
|
-
* await
|
|
1219
|
+
* await this.mailer.send(this.payload.to, this.payload.subject, this.payload.body)
|
|
883
1220
|
* }
|
|
884
1221
|
*
|
|
885
1222
|
* async failed(error: Error) {
|
|
@@ -890,9 +1227,38 @@ declare class ScheduleBuilder implements PromiseLike<ScheduleResult> {
|
|
|
890
1227
|
*/
|
|
891
1228
|
declare abstract class Job<Payload = any> {
|
|
892
1229
|
#private;
|
|
893
|
-
/**
|
|
1230
|
+
/**
|
|
1231
|
+
* Static options for this job class.
|
|
1232
|
+
*
|
|
1233
|
+
* Override this property in subclasses to configure job behavior
|
|
1234
|
+
* such as queue name, retry policy, timeout, and more.
|
|
1235
|
+
*
|
|
1236
|
+
* @example
|
|
1237
|
+
* ```typescript
|
|
1238
|
+
* class SendEmailJob extends Job<SendEmailPayload> {
|
|
1239
|
+
* static options = {
|
|
1240
|
+
* queue: 'emails',
|
|
1241
|
+
* maxRetries: 3,
|
|
1242
|
+
* timeout: '30s',
|
|
1243
|
+
* }
|
|
1244
|
+
* }
|
|
1245
|
+
* ```
|
|
1246
|
+
*/
|
|
894
1247
|
static options: JobOptions;
|
|
895
|
-
/**
|
|
1248
|
+
/**
|
|
1249
|
+
* The payload data passed to this job instance.
|
|
1250
|
+
*
|
|
1251
|
+
* Contains the data provided when the job was dispatched.
|
|
1252
|
+
* Available after the job has been hydrated by the worker.
|
|
1253
|
+
*
|
|
1254
|
+
* @example
|
|
1255
|
+
* ```typescript
|
|
1256
|
+
* async execute() {
|
|
1257
|
+
* const { to, subject, body } = this.payload
|
|
1258
|
+
* await sendEmail(to, subject, body)
|
|
1259
|
+
* }
|
|
1260
|
+
* ```
|
|
1261
|
+
*/
|
|
896
1262
|
get payload(): Payload;
|
|
897
1263
|
/**
|
|
898
1264
|
* Context information for the current job execution.
|
|
@@ -912,12 +1278,36 @@ declare abstract class Job<Payload = any> {
|
|
|
912
1278
|
*/
|
|
913
1279
|
get context(): JobContext;
|
|
914
1280
|
/**
|
|
915
|
-
*
|
|
1281
|
+
* The abort signal for timeout handling.
|
|
1282
|
+
*
|
|
1283
|
+
* Check `signal.aborted` in long-running operations to handle timeouts gracefully.
|
|
1284
|
+
*
|
|
1285
|
+
* @example
|
|
1286
|
+
* ```typescript
|
|
1287
|
+
* async execute() {
|
|
1288
|
+
* for (const item of this.payload.items) {
|
|
1289
|
+
* if (this.signal?.aborted) {
|
|
1290
|
+
* throw new Error('Job timed out')
|
|
1291
|
+
* }
|
|
1292
|
+
* await processItem(item)
|
|
1293
|
+
* }
|
|
1294
|
+
* }
|
|
1295
|
+
* ```
|
|
1296
|
+
*/
|
|
1297
|
+
get signal(): AbortSignal | undefined;
|
|
1298
|
+
/**
|
|
1299
|
+
* Hydrate the job with payload, context, and optional abort signal.
|
|
1300
|
+
*
|
|
1301
|
+
* This method is called by the worker after instantiation to provide
|
|
1302
|
+
* the job's runtime data. It should not be called directly by user code.
|
|
916
1303
|
*
|
|
917
1304
|
* @param payload - The data to be processed by this job
|
|
918
|
-
* @param context - The job execution context
|
|
1305
|
+
* @param context - The job execution context
|
|
1306
|
+
* @param signal - Optional abort signal for timeout handling
|
|
1307
|
+
*
|
|
1308
|
+
* @internal
|
|
919
1309
|
*/
|
|
920
|
-
|
|
1310
|
+
$hydrate(payload: Payload, context: JobContext, signal?: AbortSignal): void;
|
|
921
1311
|
/**
|
|
922
1312
|
* Dispatch this job to the queue.
|
|
923
1313
|
*
|
|
@@ -941,7 +1331,35 @@ declare abstract class Job<Payload = any> {
|
|
|
941
1331
|
* .run()
|
|
942
1332
|
* ```
|
|
943
1333
|
*/
|
|
944
|
-
static dispatch<T extends Job>(this: new (
|
|
1334
|
+
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>;
|
|
1335
|
+
/**
|
|
1336
|
+
* Dispatch multiple jobs to the queue in a single batch.
|
|
1337
|
+
*
|
|
1338
|
+
* Returns a JobBatchDispatcher for fluent configuration before dispatching.
|
|
1339
|
+
* The jobs are not actually dispatched until `.run()` is called or the
|
|
1340
|
+
* dispatcher is awaited.
|
|
1341
|
+
*
|
|
1342
|
+
* This is more efficient than calling `dispatch()` multiple times as it
|
|
1343
|
+
* uses batched operations (e.g., Redis pipeline, SQL batch insert).
|
|
1344
|
+
*
|
|
1345
|
+
* @param payloads - Array of data to pass to each job
|
|
1346
|
+
* @returns A JobBatchDispatcher for fluent configuration
|
|
1347
|
+
*
|
|
1348
|
+
* @example
|
|
1349
|
+
* ```typescript
|
|
1350
|
+
* // Batch dispatch for newsletter
|
|
1351
|
+
* const { jobIds } = await SendEmailJob.dispatchMany([
|
|
1352
|
+
* { to: 'user1@example.com', subject: 'Newsletter' },
|
|
1353
|
+
* { to: 'user2@example.com', subject: 'Newsletter' },
|
|
1354
|
+
* ])
|
|
1355
|
+
* .group('newsletter-jan-2025')
|
|
1356
|
+
* .toQueue('emails')
|
|
1357
|
+
* .run()
|
|
1358
|
+
*
|
|
1359
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
1360
|
+
* ```
|
|
1361
|
+
*/
|
|
1362
|
+
static dispatchMany<T extends Job>(this: new (...args: any[]) => T, payloads: (T extends Job<infer P> ? P : never)[]): JobBatchDispatcher<T extends Job<infer P> ? P : never>;
|
|
945
1363
|
/**
|
|
946
1364
|
* Create a schedule for this job.
|
|
947
1365
|
*
|
|
@@ -967,22 +1385,22 @@ declare abstract class Job<Payload = any> {
|
|
|
967
1385
|
* .run()
|
|
968
1386
|
* ```
|
|
969
1387
|
*/
|
|
970
|
-
static schedule<T extends Job>(this: new (
|
|
1388
|
+
static schedule<T extends Job>(this: new (...args: any[]) => T, payload: T extends Job<infer P> ? P : never): ScheduleBuilder;
|
|
971
1389
|
/**
|
|
972
1390
|
* Execute the job's business logic.
|
|
973
1391
|
*
|
|
974
1392
|
* This method is called by the worker when processing the job.
|
|
975
1393
|
* Implement your job's logic here.
|
|
976
1394
|
*
|
|
977
|
-
*
|
|
978
|
-
*
|
|
1395
|
+
* For timeout handling, use `this.signal` which is available after hydration.
|
|
1396
|
+
*
|
|
979
1397
|
* @throws Any error thrown will trigger retry logic (if configured)
|
|
980
1398
|
*
|
|
981
1399
|
* @example
|
|
982
1400
|
* ```typescript
|
|
983
|
-
* async execute(
|
|
1401
|
+
* async execute() {
|
|
984
1402
|
* for (const item of this.payload.items) {
|
|
985
|
-
* if (signal?.aborted) {
|
|
1403
|
+
* if (this.signal?.aborted) {
|
|
986
1404
|
* throw new Error('Job timed out')
|
|
987
1405
|
* }
|
|
988
1406
|
* await processItem(item)
|
|
@@ -990,7 +1408,7 @@ declare abstract class Job<Payload = any> {
|
|
|
990
1408
|
* }
|
|
991
1409
|
* ```
|
|
992
1410
|
*/
|
|
993
|
-
abstract execute(
|
|
1411
|
+
abstract execute(): Promise<void>;
|
|
994
1412
|
/**
|
|
995
1413
|
* Called when the job has permanently failed (after all retries exhausted).
|
|
996
1414
|
*
|
|
@@ -1010,4 +1428,4 @@ declare abstract class Job<Payload = any> {
|
|
|
1010
1428
|
failed?(error: Error): Promise<void>;
|
|
1011
1429
|
}
|
|
1012
1430
|
|
|
1013
|
-
export { type Adapter as A, type BackoffStrategy as B, type
|
|
1431
|
+
export { type Adapter as A, type BackoffStrategy as B, type DispatchManyResult as D, type JobRetention 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 JobRecord as b, type JobData as c, type ScheduleData as d, type ScheduleListOptions as e, type JobFactory as f, type JobOptions as g, Job as h, type JobClass as i, type ScheduleStatus as j, ScheduleBuilder as k, JobBatchDispatcher as l, type AdapterFactory as m, customBackoff as n, linearBackoff as o, exponentialBackoff as p, fixedBackoff as q, type Duration as r, type JobStatus as s, type DispatchResult as t, type JobContext as u, type BackoffConfig as v, type QueueConfig as w, type WorkerConfig as x, type ScheduleResult as y };
|