@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.
@@ -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
- type JobClass<T extends Job = Job> = (new (payload: any, context: JobContext) => T) & {
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, payload, and context, and must return
260
- * a job instance (or a Promise that resolves to one).
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
- * const worker = new Worker({
271
- * worker: {
272
- * jobFactory: async (JobClass, payload, context) => {
273
- * return app.container.make(JobClass, [payload, context])
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, payload: any, context: JobContext) => Job | Promise<Job>;
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
- jobName: string;
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
- jobName: string;
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(payload, context)`.
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, payload, context) => {
457
- * return app.container.make(JobClass, [payload, context])
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(jobName: string, payload: any);
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
- * constructor(payload: SendEmailPayload, context: JobContext) {
877
- * super(payload, context)
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 sendEmail(this.payload.to, this.payload.subject, this.payload.body)
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
- /** Static options for this job class (queue, retries, timeout, etc.) */
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
- /** The payload data passed to this job instance */
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
- * Create a new job instance.
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 (provided by the worker)
1305
+ * @param context - The job execution context
1306
+ * @param signal - Optional abort signal for timeout handling
1307
+ *
1308
+ * @internal
919
1309
  */
920
- constructor(payload: Payload, context: JobContext);
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 (payload: any, context: JobContext) => T, payload: T extends Job<infer P> ? P : never): JobDispatcher<T extends Job<infer P> ? P : never>;
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 (payload: any, context: JobContext) => T, payload: T extends Job<infer P> ? P : never): ScheduleBuilder;
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
- * @param signal - Optional AbortSignal for timeout handling.
978
- * Check `signal.aborted` for long-running operations.
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(signal?: AbortSignal) {
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(signal?: AbortSignal): Promise<void>;
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 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 };
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 };