@boringnode/queue 0.0.1-alpha.2 → 0.0.1-alpha.4

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.
@@ -0,0 +1,776 @@
1
+ /**
2
+ * Calculates retry delays using configurable strategies.
3
+ *
4
+ * Supports three built-in strategies:
5
+ * - `exponential`: Delay doubles each attempt (1s, 2s, 4s, 8s, ...)
6
+ * - `linear`: Delay increases linearly (5s, 10s, 15s, 20s, ...)
7
+ * - `fixed`: Same delay every time (10s, 10s, 10s, ...)
8
+ *
9
+ * All strategies support:
10
+ * - `maxDelay`: Cap the maximum delay
11
+ * - `jitter`: Add randomness to prevent thundering herd
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const strategy = new BackoffStrategy({
16
+ * strategy: 'exponential',
17
+ * baseDelay: '1s',
18
+ * maxDelay: '5m',
19
+ * multiplier: 2,
20
+ * jitter: true,
21
+ * })
22
+ *
23
+ * strategy.calculateDelay(1) // ~1000ms
24
+ * strategy.calculateDelay(2) // ~2000ms
25
+ * strategy.calculateDelay(3) // ~4000ms
26
+ * ```
27
+ */
28
+ declare class BackoffStrategy$1 {
29
+ #private;
30
+ /**
31
+ * Create a new backoff strategy.
32
+ *
33
+ * @param config - Backoff configuration
34
+ * @throws {E_INVALID_BASE_DELAY} If baseDelay is not positive
35
+ * @throws {E_INVALID_MAX_DELAY} If maxDelay is invalid
36
+ * @throws {E_INVALID_MULTIPLIER} If multiplier is invalid
37
+ */
38
+ constructor(config: BackoffConfig);
39
+ /**
40
+ * Calculate the delay for a given attempt number.
41
+ *
42
+ * @param attempt - The attempt number (1-based)
43
+ * @returns Delay in milliseconds
44
+ * @throws {RuntimeException} If attempt is less than 1
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * // Exponential: 1s, 2s, 4s, 8s, 16s, ...
49
+ * strategy.calculateDelay(1) // 1000
50
+ * strategy.calculateDelay(2) // 2000
51
+ * strategy.calculateDelay(3) // 4000
52
+ * ```
53
+ */
54
+ calculateDelay(attempt: number): number;
55
+ /**
56
+ * Get the Date when the next retry should occur.
57
+ *
58
+ * @param attempt - The attempt number (1-based)
59
+ * @returns Date for the next retry
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const nextRetry = strategy.getNextRetryAt(3)
64
+ * console.log(`Retry at: ${nextRetry.toISOString()}`)
65
+ * ```
66
+ */
67
+ getNextRetryAt(attempt: number): Date;
68
+ /**
69
+ * Get a frozen copy of the configuration.
70
+ *
71
+ * @returns Readonly configuration object
72
+ */
73
+ getConfig(): Readonly<BackoffConfig>;
74
+ }
75
+ /**
76
+ * Create an exponential backoff strategy factory.
77
+ *
78
+ * Delay doubles with each attempt: 1s → 2s → 4s → 8s → ...
79
+ *
80
+ * Default config:
81
+ * - baseDelay: 1s
82
+ * - maxDelay: 5m
83
+ * - multiplier: 2
84
+ * - jitter: true
85
+ *
86
+ * @param config - Optional overrides for default config
87
+ * @returns Factory function for creating BackoffStrategy instances
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const config = {
92
+ * retry: {
93
+ * maxRetries: 5,
94
+ * backoff: exponentialBackoff({ baseDelay: '500ms', maxDelay: '1m' }),
95
+ * },
96
+ * }
97
+ * ```
98
+ */
99
+ declare function exponentialBackoff(config?: Partial<Omit<BackoffConfig, 'strategy'>>): () => BackoffStrategy$1;
100
+ /**
101
+ * Create a linear backoff strategy factory.
102
+ *
103
+ * Delay increases linearly: 5s → 10s → 15s → 20s → ...
104
+ *
105
+ * Default config:
106
+ * - baseDelay: 5s
107
+ * - maxDelay: 2m
108
+ *
109
+ * @param config - Optional overrides for default config
110
+ * @returns Factory function for creating BackoffStrategy instances
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * const config = {
115
+ * retry: {
116
+ * maxRetries: 3,
117
+ * backoff: linearBackoff({ baseDelay: '10s' }),
118
+ * },
119
+ * }
120
+ * ```
121
+ */
122
+ declare function linearBackoff(config?: Partial<Omit<BackoffConfig, 'strategy'>>): () => BackoffStrategy$1;
123
+ /**
124
+ * Create a fixed delay backoff strategy factory.
125
+ *
126
+ * Same delay every time: 10s → 10s → 10s → ...
127
+ *
128
+ * @param delay - The fixed delay (default: '10s')
129
+ * @returns Factory function for creating BackoffStrategy instances
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const config = {
134
+ * retry: {
135
+ * maxRetries: 3,
136
+ * backoff: fixedBackoff('30s'),
137
+ * },
138
+ * }
139
+ * ```
140
+ */
141
+ declare function fixedBackoff(delay?: Duration): () => BackoffStrategy$1;
142
+ /**
143
+ * Create a custom backoff strategy factory.
144
+ *
145
+ * Use this when you need full control over the configuration.
146
+ *
147
+ * @param config - Complete backoff configuration
148
+ * @returns Factory function for creating BackoffStrategy instances
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * const config = {
153
+ * retry: {
154
+ * maxRetries: 5,
155
+ * backoff: customBackoff({
156
+ * strategy: 'exponential',
157
+ * baseDelay: '100ms',
158
+ * maxDelay: '30s',
159
+ * multiplier: 3,
160
+ * jitter: false,
161
+ * }),
162
+ * },
163
+ * }
164
+ * ```
165
+ */
166
+ declare function customBackoff(config: BackoffConfig): () => BackoffStrategy$1;
167
+
168
+ interface LogObject {
169
+ [key: string]: unknown;
170
+ }
171
+ interface ErrorObject extends LogObject {
172
+ err?: Error;
173
+ }
174
+ interface Logger {
175
+ trace(msg: string): void;
176
+ trace(obj: LogObject, msg: string): void;
177
+ debug(msg: string): void;
178
+ debug(obj: LogObject, msg: string): void;
179
+ info(msg: string): void;
180
+ info(obj: LogObject, msg: string): void;
181
+ warn(msg: string): void;
182
+ warn(obj: LogObject, msg: string): void;
183
+ error(msg: string): void;
184
+ error(obj: ErrorObject, msg: string): void;
185
+ child(obj: LogObject): Logger;
186
+ }
187
+
188
+ type Duration = number | string;
189
+ interface JobData {
190
+ id: string;
191
+ name: string;
192
+ payload: any;
193
+ attempts: number;
194
+ priority?: number;
195
+ nextRetryAt?: Date;
196
+ stalledCount?: number;
197
+ }
198
+ interface JobOptions {
199
+ queue?: string;
200
+ adapter?: string | (() => Adapter);
201
+ maxRetries?: number;
202
+ priority?: number;
203
+ retry?: RetryConfig;
204
+ timeout?: Duration;
205
+ failOnTimeout?: boolean;
206
+ }
207
+ /**
208
+ * Context information available to a job during execution.
209
+ *
210
+ * Provides metadata about the current job execution, including
211
+ * retry information, queue details, and timing.
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * class MyJob extends Job<Payload> {
216
+ * async execute() {
217
+ * console.log(`Attempt ${this.context.attempt} of job ${this.context.jobId}`)
218
+ * console.log(`Running on queue: ${this.context.queue}`)
219
+ * }
220
+ * }
221
+ * ```
222
+ */
223
+ interface JobContext {
224
+ /** Unique identifier for this job */
225
+ jobId: string;
226
+ /** Job class name */
227
+ name: string;
228
+ /** Current attempt number (1-based: first attempt = 1) */
229
+ attempt: number;
230
+ /** Queue name this job is being processed from */
231
+ queue: string;
232
+ /** Job priority (lower number = higher priority) */
233
+ priority: number;
234
+ /** When this job was acquired by the worker for processing */
235
+ acquiredAt: Date;
236
+ /** Number of times this job has been recovered from stalled state */
237
+ stalledCount: number;
238
+ }
239
+ type JobClass<T extends Job = Job> = (new (payload: any, context: JobContext) => T) & {
240
+ options?: JobOptions;
241
+ };
242
+ /**
243
+ * Factory function for custom job instantiation.
244
+ *
245
+ * Use this to integrate with IoC containers for dependency injection.
246
+ * The factory receives the job class, payload, and context, and must return
247
+ * a job instance (or a Promise that resolves to one).
248
+ *
249
+ * @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
+ * @returns The job instance, or a Promise resolving to the instance
253
+ *
254
+ * @example
255
+ * ```typescript
256
+ * // With AdonisJS IoC container
257
+ * const worker = new Worker({
258
+ * worker: {
259
+ * jobFactory: async (JobClass, payload, context) => {
260
+ * return app.container.make(JobClass, [payload, context])
261
+ * }
262
+ * }
263
+ * })
264
+ * ```
265
+ */
266
+ type JobFactory = (JobClass: JobClass, payload: any, context: JobContext) => Job | Promise<Job>;
267
+ interface RetryConfig {
268
+ maxRetries?: number;
269
+ backoff?: () => BackoffStrategy$1;
270
+ }
271
+ type BackoffStrategy = 'exponential' | 'linear' | 'fixed';
272
+ interface BackoffConfig {
273
+ strategy: BackoffStrategy;
274
+ baseDelay: Duration;
275
+ maxDelay?: Duration;
276
+ multiplier?: number;
277
+ jitter?: boolean;
278
+ }
279
+ interface QueueConfig {
280
+ adapter?: string;
281
+ retry?: any;
282
+ }
283
+ interface WorkerConfig {
284
+ /**
285
+ * Maximum number of jobs to process concurrently.
286
+ * @default 1
287
+ */
288
+ concurrency?: number;
289
+ /**
290
+ * Delay between queue polls when idle (no jobs available).
291
+ * @default '2s'
292
+ */
293
+ idleDelay?: Duration;
294
+ /**
295
+ * Maximum duration a job can run before being timed out.
296
+ * Can be overridden per job via JobOptions.timeout.
297
+ * @default undefined (no timeout)
298
+ */
299
+ timeout?: Duration;
300
+ /**
301
+ * Duration after which an active job is considered stalled.
302
+ * A stalled job is one that was acquired but the worker stopped
303
+ * responding (e.g., due to a crash).
304
+ * @default '30s'
305
+ */
306
+ stalledThreshold?: Duration;
307
+ /**
308
+ * How often to check for stalled jobs.
309
+ * @default '30s'
310
+ */
311
+ stalledInterval?: Duration;
312
+ /**
313
+ * Maximum number of times a job can be recovered from stalled state
314
+ * before being marked as failed permanently.
315
+ * @default 1
316
+ */
317
+ maxStalledCount?: number;
318
+ /**
319
+ * Whether to automatically stop the worker on SIGINT/SIGTERM signals.
320
+ * When enabled, the worker will wait for running jobs to complete
321
+ * before stopping.
322
+ * @default true
323
+ */
324
+ gracefulShutdown?: boolean;
325
+ /**
326
+ * Callback invoked when a shutdown signal is received.
327
+ * Called before the worker starts stopping.
328
+ */
329
+ onShutdownSignal?: () => void | Promise<void>;
330
+ }
331
+ type WorkerCycle = {
332
+ type: 'started';
333
+ queue: string;
334
+ job: any;
335
+ } | {
336
+ type: 'completed';
337
+ queue: string;
338
+ job: any;
339
+ } | {
340
+ type: 'idle';
341
+ suggestedDelay: Duration;
342
+ } | {
343
+ type: 'error';
344
+ error: Error;
345
+ suggestedDelay: Duration;
346
+ };
347
+ type AdapterFactory<T extends Adapter = Adapter> = () => T;
348
+ interface QueueManagerConfig {
349
+ default: string;
350
+ adapters: Record<string, AdapterFactory>;
351
+ retry?: RetryConfig;
352
+ queues?: Record<string, QueueConfig>;
353
+ worker?: WorkerConfig;
354
+ locations?: string[];
355
+ logger?: Logger;
356
+ /**
357
+ * Custom factory function for job instantiation.
358
+ *
359
+ * Use this to integrate with IoC containers for dependency injection.
360
+ * When provided, this factory is called instead of `new JobClass(payload, context)`.
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * await QueueManager.init({
365
+ * default: 'redis',
366
+ * adapters: { redis: redis() },
367
+ * jobFactory: async (JobClass, payload, context) => {
368
+ * return app.container.make(JobClass, [payload, context])
369
+ * }
370
+ * })
371
+ * ```
372
+ */
373
+ jobFactory?: JobFactory;
374
+ }
375
+
376
+ /**
377
+ * A job that has been acquired by a worker for processing.
378
+ * Extends JobData with the timestamp when the job was acquired.
379
+ */
380
+ interface AcquiredJob extends JobData {
381
+ /** Timestamp (in ms) when the job was acquired by the worker */
382
+ acquiredAt: number;
383
+ }
384
+ /**
385
+ * Adapter interface for queue storage backends.
386
+ *
387
+ * Implementations handle job persistence, atomic operations, and
388
+ * concurrency control. Built-in adapters: Redis, Knex (PostgreSQL/SQLite).
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * import { redis } from '@boringnode/queue'
393
+ *
394
+ * const config = {
395
+ * default: 'redis',
396
+ * adapters: {
397
+ * redis: redis({ host: 'localhost', port: 6379 })
398
+ * }
399
+ * }
400
+ * ```
401
+ */
402
+ interface Adapter {
403
+ /**
404
+ * Set the worker ID for this adapter instance.
405
+ * Required before calling pop methods when consuming jobs.
406
+ *
407
+ * @param workerId - Unique identifier for the worker
408
+ */
409
+ setWorkerId(workerId: string): void;
410
+ /**
411
+ * Pop the next available job from the default queue.
412
+ * Atomically moves the job from pending to active state.
413
+ *
414
+ * @returns The acquired job, or null if queue is empty
415
+ */
416
+ pop(): Promise<AcquiredJob | null>;
417
+ /**
418
+ * Pop the next available job from a specific queue.
419
+ * Atomically moves the job from pending to active state.
420
+ *
421
+ * @param queue - The queue name to pop from
422
+ * @returns The acquired job, or null if queue is empty
423
+ */
424
+ popFrom(queue: string): Promise<AcquiredJob | null>;
425
+ /**
426
+ * Recover stalled jobs that have been active for too long.
427
+ * A stalled job is one where the worker stopped responding (e.g., crash).
428
+ *
429
+ * Jobs within maxStalledCount are moved back to pending.
430
+ * Jobs exceeding maxStalledCount are failed permanently.
431
+ *
432
+ * @param queue - The queue to check for stalled jobs
433
+ * @param stalledThreshold - Duration in ms after which a job is considered stalled
434
+ * @param maxStalledCount - Maximum times a job can be recovered before failing
435
+ * @returns Number of jobs that were recovered (not including permanently failed ones)
436
+ */
437
+ recoverStalledJobs(queue: string, stalledThreshold: number, maxStalledCount: number): Promise<number>;
438
+ /**
439
+ * Mark a job as completed and remove it from the queue.
440
+ *
441
+ * @param jobId - The job ID to complete
442
+ * @param queue - The queue the job belongs to
443
+ */
444
+ completeJob(jobId: string, queue: string): Promise<void>;
445
+ /**
446
+ * Mark a job as failed permanently and remove it from the queue.
447
+ *
448
+ * @param jobId - The job ID to fail
449
+ * @param queue - The queue the job belongs to
450
+ * @param error - Optional error that caused the failure
451
+ */
452
+ failJob(jobId: string, queue: string, error?: Error): Promise<void>;
453
+ /**
454
+ * Retry a job by moving it back to pending with incremented attempts.
455
+ *
456
+ * @param jobId - The job ID to retry
457
+ * @param queue - The queue the job belongs to
458
+ * @param retryAt - Optional future date to delay the retry
459
+ */
460
+ retryJob(jobId: string, queue: string, retryAt?: Date): Promise<void>;
461
+ /**
462
+ * Push a job to the default queue for immediate processing.
463
+ *
464
+ * @param jobData - The job data to push
465
+ */
466
+ push(jobData: JobData): Promise<void>;
467
+ /**
468
+ * Push a job to a specific queue for immediate processing.
469
+ *
470
+ * @param queue - The queue name to push to
471
+ * @param jobData - The job data to push
472
+ */
473
+ pushOn(queue: string, jobData: JobData): Promise<void>;
474
+ /**
475
+ * Push a job to the default queue with a delay.
476
+ *
477
+ * @param jobData - The job data to push
478
+ * @param delay - Delay in milliseconds before the job becomes available
479
+ */
480
+ pushLater(jobData: JobData, delay: number): Promise<void>;
481
+ /**
482
+ * Push a job to a specific queue with a delay.
483
+ *
484
+ * @param queue - The queue name to push to
485
+ * @param jobData - The job data to push
486
+ * @param delay - Delay in milliseconds before the job becomes available
487
+ */
488
+ pushLaterOn(queue: string, jobData: JobData, delay: number): Promise<void>;
489
+ /**
490
+ * Get the number of pending jobs in the default queue.
491
+ *
492
+ * @returns The number of pending jobs
493
+ */
494
+ size(): Promise<number>;
495
+ /**
496
+ * Get the number of pending jobs in a specific queue.
497
+ *
498
+ * @param queue - The queue name to check
499
+ * @returns The number of pending jobs
500
+ */
501
+ sizeOf(queue: string): Promise<number>;
502
+ /**
503
+ * Clean up resources (close connections, etc.).
504
+ * Called when the worker stops or the adapter is no longer needed.
505
+ */
506
+ destroy(): Promise<void>;
507
+ }
508
+
509
+ /**
510
+ * Fluent builder for dispatching jobs to the queue.
511
+ *
512
+ * Provides a chainable API for configuring job options before dispatch.
513
+ * Usually created via `Job.dispatch()` rather than directly.
514
+ *
515
+ * ```
516
+ * Job.dispatch(payload)
517
+ * .toQueue('emails') // optional: target queue
518
+ * .priority(1) // optional: 1-10, lower = higher priority
519
+ * .in('5m') // optional: delay before processing
520
+ * .with('redis') // optional: specific adapter
521
+ * .run() // dispatch the job
522
+ * ```
523
+ *
524
+ * @typeParam T - The payload type for this job
525
+ *
526
+ * @example
527
+ * ```typescript
528
+ * // Simple dispatch (auto-runs via thenable)
529
+ * await SendEmailJob.dispatch({ to: 'user@example.com', subject: 'Hello' })
530
+ *
531
+ * // With options
532
+ * const jobId = await SendEmailJob.dispatch({ to: 'user@example.com' })
533
+ * .toQueue('high-priority')
534
+ * .priority(1)
535
+ * .run()
536
+ *
537
+ * // Delayed job
538
+ * await ReminderJob.dispatch({ userId: 123 }).in('24h')
539
+ * ```
540
+ */
541
+ declare class JobDispatcher<T> {
542
+ #private;
543
+ /**
544
+ * Create a new job dispatcher.
545
+ *
546
+ * @param name - The job class name (used to locate the class at runtime)
547
+ * @param payload - The data to pass to the job
548
+ */
549
+ constructor(name: string, payload: T);
550
+ /**
551
+ * Set the target queue for this job.
552
+ *
553
+ * @param queue - Queue name (default: 'default')
554
+ * @returns This dispatcher for chaining
555
+ *
556
+ * @example
557
+ * ```typescript
558
+ * await SendEmailJob.dispatch(payload).toQueue('emails')
559
+ * ```
560
+ */
561
+ toQueue(queue: string): this;
562
+ /**
563
+ * Delay the job execution.
564
+ *
565
+ * The job will be stored in a delayed state and moved to pending
566
+ * after the delay expires.
567
+ *
568
+ * @param delay - Delay as milliseconds or duration string ('5s', '1h', '7d')
569
+ * @returns This dispatcher for chaining
570
+ *
571
+ * @example
572
+ * ```typescript
573
+ * // Send reminder in 24 hours
574
+ * await ReminderJob.dispatch(payload).in('24h')
575
+ *
576
+ * // Process in 5 minutes
577
+ * await CleanupJob.dispatch(payload).in('5m')
578
+ * ```
579
+ */
580
+ in(delay: Duration): this;
581
+ /**
582
+ * Set the job priority.
583
+ *
584
+ * Lower numbers = higher priority. Jobs with lower priority values
585
+ * are processed before jobs with higher values.
586
+ *
587
+ * @param priority - Priority level (1-10, default: 5)
588
+ * @returns This dispatcher for chaining
589
+ *
590
+ * @example
591
+ * ```typescript
592
+ * // High priority job
593
+ * await UrgentJob.dispatch(payload).priority(1)
594
+ *
595
+ * // Low priority job
596
+ * await BackgroundJob.dispatch(payload).priority(10)
597
+ * ```
598
+ */
599
+ priority(priority: number): this;
600
+ /**
601
+ * Use a specific adapter for this job.
602
+ *
603
+ * @param adapter - Adapter name or factory function
604
+ * @returns This dispatcher for chaining
605
+ *
606
+ * @example
607
+ * ```typescript
608
+ * // Use named adapter
609
+ * await Job.dispatch(payload).with('redis')
610
+ *
611
+ * // Use custom adapter instance
612
+ * await Job.dispatch(payload).with(() => new CustomAdapter())
613
+ * ```
614
+ */
615
+ with(adapter: string | (() => Adapter)): this;
616
+ /**
617
+ * Dispatch the job to the queue.
618
+ *
619
+ * @returns The unique job ID
620
+ *
621
+ * @example
622
+ * ```typescript
623
+ * const jobId = await SendEmailJob.dispatch(payload).run()
624
+ * console.log(`Dispatched job: ${jobId}`)
625
+ * ```
626
+ */
627
+ run(): Promise<`${string}-${string}-${string}-${string}-${string}`>;
628
+ /**
629
+ * Thenable implementation for auto-dispatch when awaited.
630
+ *
631
+ * Allows `await Job.dispatch(payload)` without explicit `.run()`.
632
+ *
633
+ * @param onFulfilled - Success callback
634
+ * @param onRejected - Error callback
635
+ * @returns Promise resolving to the job ID
636
+ */
637
+ then(onFulfilled?: (value: string) => any, onRejected?: (reason: any) => any): Promise<any>;
638
+ }
639
+
640
+ /**
641
+ * Abstract base class for all queue jobs.
642
+ *
643
+ * Extend this class to create your own jobs. Each job must implement
644
+ * the `execute()` method which contains the job's business logic.
645
+ *
646
+ * @typeParam Payload - The type of data this job receives
647
+ *
648
+ * @example
649
+ * ```typescript
650
+ * import { Job } from '@boringnode/queue'
651
+ * import type { JobContext } from '@boringnode/queue'
652
+ *
653
+ * interface SendEmailPayload {
654
+ * to: string
655
+ * subject: string
656
+ * body: string
657
+ * }
658
+ *
659
+ * export default class SendEmailJob extends Job<SendEmailPayload> {
660
+ * static options = {
661
+ * queue: 'emails',
662
+ * maxRetries: 3,
663
+ * }
664
+ *
665
+ * constructor(payload: SendEmailPayload, context: JobContext) {
666
+ * super(payload, context)
667
+ * }
668
+ *
669
+ * async execute() {
670
+ * console.log(`Attempt ${this.context.attempt} for job ${this.context.jobId}`)
671
+ * await sendEmail(this.payload.to, this.payload.subject, this.payload.body)
672
+ * }
673
+ *
674
+ * async failed(error: Error) {
675
+ * console.error(`Failed to send email to ${this.payload.to}:`, error)
676
+ * }
677
+ * }
678
+ * ```
679
+ */
680
+ declare abstract class Job<Payload = any> {
681
+ #private;
682
+ /** Static options for this job class (queue, retries, timeout, etc.) */
683
+ static options: JobOptions;
684
+ /** The payload data passed to this job instance */
685
+ get payload(): Payload;
686
+ /**
687
+ * Context information for the current job execution.
688
+ *
689
+ * Provides metadata such as job ID, current attempt number,
690
+ * queue name, priority, and timing information.
691
+ *
692
+ * @example
693
+ * ```typescript
694
+ * async execute() {
695
+ * if (this.context.attempt > 1) {
696
+ * console.log(`Retry attempt ${this.context.attempt}`)
697
+ * }
698
+ * console.log(`Processing job ${this.context.jobId} on queue ${this.context.queue}`)
699
+ * }
700
+ * ```
701
+ */
702
+ get context(): JobContext;
703
+ /**
704
+ * Create a new job instance.
705
+ *
706
+ * @param payload - The data to be processed by this job
707
+ * @param context - The job execution context (provided by the worker)
708
+ */
709
+ constructor(payload: Payload, context: JobContext);
710
+ /**
711
+ * Dispatch this job to the queue.
712
+ *
713
+ * Returns a JobDispatcher for fluent configuration before dispatching.
714
+ * The job is not actually dispatched until `.run()` is called or the
715
+ * dispatcher is awaited.
716
+ *
717
+ * @param payload - The data to pass to the job
718
+ * @returns A JobDispatcher for fluent configuration
719
+ *
720
+ * @example
721
+ * ```typescript
722
+ * // Simple dispatch
723
+ * await SendEmailJob.dispatch({ to: 'user@example.com', subject: 'Hello' })
724
+ *
725
+ * // With options
726
+ * await SendEmailJob.dispatch({ to: 'user@example.com' })
727
+ * .toQueue('high-priority')
728
+ * .priority(1)
729
+ * .in('5m')
730
+ * .run()
731
+ * ```
732
+ */
733
+ 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>;
734
+ /**
735
+ * Execute the job's business logic.
736
+ *
737
+ * This method is called by the worker when processing the job.
738
+ * Implement your job's logic here.
739
+ *
740
+ * @param signal - Optional AbortSignal for timeout handling.
741
+ * Check `signal.aborted` for long-running operations.
742
+ * @throws Any error thrown will trigger retry logic (if configured)
743
+ *
744
+ * @example
745
+ * ```typescript
746
+ * async execute(signal?: AbortSignal) {
747
+ * for (const item of this.payload.items) {
748
+ * if (signal?.aborted) {
749
+ * throw new Error('Job timed out')
750
+ * }
751
+ * await processItem(item)
752
+ * }
753
+ * }
754
+ * ```
755
+ */
756
+ abstract execute(signal?: AbortSignal): Promise<void>;
757
+ /**
758
+ * Called when the job has permanently failed (after all retries exhausted).
759
+ *
760
+ * Use this hook for cleanup, logging, or notifications.
761
+ * This is optional - implement only if you need failure handling.
762
+ *
763
+ * @param error - The error that caused the final failure
764
+ *
765
+ * @example
766
+ * ```typescript
767
+ * async failed(error: Error) {
768
+ * await notifyAdmin(`Job failed: ${error.message}`)
769
+ * await cleanup(this.payload)
770
+ * }
771
+ * ```
772
+ */
773
+ failed?(error: Error): Promise<void>;
774
+ }
775
+
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 JobFactory as b, Job as c, type JobClass as d, customBackoff as e, exponentialBackoff as f, fixedBackoff as g, type JobOptions as h, type JobContext as i, type BackoffConfig as j, type QueueConfig as k, linearBackoff as l, type WorkerConfig as m, type AdapterFactory as n };