@igniter-js/jobs 0.1.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.
@@ -0,0 +1,1411 @@
1
+ import { StandardSchemaV1 } from '@igniter-js/core';
2
+
3
+ /**
4
+ * @fileoverview Scope and actor types for @igniter-js/jobs
5
+ * @module @igniter-js/jobs/types/scope
6
+ */
7
+ /**
8
+ * Options for defining a scope in the jobs builder.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const jobs = IgniterJobs.create<AppContext>()
13
+ * .addScope('organization', { required: true })
14
+ * .addScope('tenant', { required: false })
15
+ * .build()
16
+ * ```
17
+ */
18
+ interface IgniterJobScopeOptions {
19
+ /**
20
+ * Whether the scope identifier is required when dispatching jobs.
21
+ * If true, all job dispatches must include this scope.
22
+ * @default false
23
+ */
24
+ required?: boolean;
25
+ /**
26
+ * Optional description for the scope (for documentation).
27
+ */
28
+ description?: string;
29
+ }
30
+ /**
31
+ * Options for defining an actor in the jobs builder.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const jobs = IgniterJobs.create<AppContext>()
36
+ * .addActor('user', { description: 'The user who initiated the job' })
37
+ * .build()
38
+ * ```
39
+ */
40
+ interface IgniterJobActorOptions {
41
+ /**
42
+ * Optional description for the actor (for documentation).
43
+ */
44
+ description?: string;
45
+ }
46
+ /**
47
+ * A scope entry attached to a job.
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const scopeEntry: IgniterJobScopeEntry = {
52
+ * id: 'org_123',
53
+ * tags: { plan: 'enterprise', region: 'us-east-1' },
54
+ * }
55
+ * ```
56
+ */
57
+ interface IgniterJobScopeEntry {
58
+ /**
59
+ * The unique identifier for the scope (e.g., organization ID, tenant ID).
60
+ */
61
+ id: string;
62
+ /**
63
+ * Optional tags for additional metadata.
64
+ */
65
+ tags?: Record<string, string | number | boolean>;
66
+ }
67
+ /**
68
+ * An actor entry attached to a job.
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const actorEntry: IgniterJobActorEntry = {
73
+ * id: 'user_456',
74
+ * tags: { role: 'admin', email: 'admin@example.com' },
75
+ * }
76
+ * ```
77
+ */
78
+ interface IgniterJobActorEntry {
79
+ /**
80
+ * The unique identifier for the actor (e.g., user ID).
81
+ * Optional to support system-initiated jobs.
82
+ */
83
+ id?: string;
84
+ /**
85
+ * Optional tags for additional metadata.
86
+ */
87
+ tags?: Record<string, string | number | boolean>;
88
+ }
89
+
90
+ /**
91
+ * @fileoverview Job definition types for @igniter-js/jobs
92
+ * @module @igniter-js/jobs/types/job
93
+ */
94
+
95
+ /**
96
+ * Backoff strategy for job retries.
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * // Exponential backoff: 1s, 2s, 4s, 8s, ...
101
+ * const exponential: IgniterJobBackoff = {
102
+ * type: 'exponential',
103
+ * delay: 1000,
104
+ * maxDelay: 30000,
105
+ * }
106
+ *
107
+ * // Fixed delays: 1s, 1s, 1s, ...
108
+ * const fixed: IgniterJobBackoff = {
109
+ * type: 'fixed',
110
+ * delay: 1000,
111
+ * }
112
+ *
113
+ * // Linear delays: 1s, 2s, 3s, 4s, ...
114
+ * const linear: IgniterJobBackoff = {
115
+ * type: 'linear',
116
+ * delay: 1000,
117
+ * }
118
+ *
119
+ * // Custom delays: 1s, 5s, 30s
120
+ * const custom: IgniterJobBackoff = {
121
+ * type: 'custom',
122
+ * delays: [1000, 5000, 30000],
123
+ * }
124
+ * ```
125
+ */
126
+ type IgniterJobBackoff = {
127
+ type: 'exponential';
128
+ delay: number;
129
+ maxDelay?: number;
130
+ } | {
131
+ type: 'fixed';
132
+ delay: number;
133
+ } | {
134
+ type: 'linear';
135
+ delay: number;
136
+ } | {
137
+ type: 'custom';
138
+ delays: number[];
139
+ };
140
+ /**
141
+ * Rate limiter configuration for jobs.
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * // Max 100 jobs per minute
146
+ * const limiter: IgniterJobLimiter = {
147
+ * max: 100,
148
+ * duration: 60000, // 1 minute in milliseconds
149
+ * }
150
+ * ```
151
+ */
152
+ interface IgniterJobLimiter {
153
+ /**
154
+ * Maximum number of jobs to process within the duration window.
155
+ */
156
+ max: number;
157
+ /**
158
+ * Duration window in milliseconds.
159
+ */
160
+ duration: number;
161
+ }
162
+ /**
163
+ * Context passed to job handlers.
164
+ *
165
+ * @typeParam TContext - Application context type
166
+ * @typeParam TInput - Job input type
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const handler = async (ctx: IgniterJobHandlerContext<AppContext, { userId: string }>) => {
171
+ * const { input, context, job, attempt, log, updateProgress } = ctx
172
+ *
173
+ * log('info', `Processing user ${input.userId}`)
174
+ * await updateProgress(50)
175
+ *
176
+ * const user = await context.db.users.findById(input.userId)
177
+ * return { success: true, user }
178
+ * }
179
+ * ```
180
+ */
181
+ interface IgniterJobHandlerContext<TContext, TInput> {
182
+ /**
183
+ * The validated job input data.
184
+ */
185
+ input: TInput;
186
+ /**
187
+ * Application context provided during build.
188
+ */
189
+ context: TContext;
190
+ /**
191
+ * Job metadata and identifiers.
192
+ */
193
+ job: {
194
+ /**
195
+ * Unique job identifier.
196
+ */
197
+ id: string;
198
+ /**
199
+ * Job name (from addJob).
200
+ */
201
+ name: string;
202
+ /**
203
+ * Queue name the job belongs to.
204
+ */
205
+ queue: string;
206
+ /**
207
+ * Unix timestamp when job was created.
208
+ */
209
+ timestamp: number;
210
+ };
211
+ /**
212
+ * Current attempt number (1-indexed).
213
+ */
214
+ attempt: number;
215
+ /**
216
+ * Scope entry if provided during dispatch.
217
+ */
218
+ scope?: IgniterJobScopeEntry;
219
+ /**
220
+ * Actor entry if provided during dispatch.
221
+ */
222
+ actor?: IgniterJobActorEntry;
223
+ /**
224
+ * Log a message associated with this job.
225
+ *
226
+ * @param level - Log level
227
+ * @param message - Message to log
228
+ */
229
+ log: (level: 'info' | 'warn' | 'error', message: string) => Promise<void>;
230
+ /**
231
+ * Update job progress (0-100).
232
+ *
233
+ * @param progress - Progress percentage
234
+ */
235
+ updateProgress: (progress: number) => Promise<void>;
236
+ }
237
+ /**
238
+ * Job handler function type.
239
+ *
240
+ * @typeParam TContext - Application context type
241
+ * @typeParam TInput - Job input type
242
+ * @typeParam TOutput - Job output type
243
+ */
244
+ type IgniterJobHandler<TContext, TInput, TOutput> = (ctx: IgniterJobHandlerContext<TContext, TInput>) => Promise<TOutput> | TOutput;
245
+ /**
246
+ * Hook called when a job fails.
247
+ */
248
+ type IgniterJobFailureHook<TContext, TInput> = (ctx: IgniterJobHandlerContext<TContext, TInput>, error: Error) => void | Promise<void>;
249
+ /**
250
+ * Hook called when a job completes successfully.
251
+ */
252
+ type IgniterJobCompleteHook<TContext, TInput, TOutput> = (ctx: IgniterJobHandlerContext<TContext, TInput>, result: TOutput) => void | Promise<void>;
253
+ /**
254
+ * Full job definition.
255
+ *
256
+ * @typeParam TContext - Application context type
257
+ * @typeParam TInput - Job input type
258
+ * @typeParam TOutput - Job output type
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * const sendEmailJob: IgniterJobDefinition<AppContext, SendEmailInput, void> = {
263
+ * input: z.object({
264
+ * to: z.string().email(),
265
+ * subject: z.string(),
266
+ * body: z.string(),
267
+ * }),
268
+ * retry: { attempts: 3, backoff: { type: 'exponential', delay: 1000 } },
269
+ * timeout: 30000,
270
+ * handler: async (ctx) => {
271
+ * await ctx.context.mailer.send(ctx.input)
272
+ * },
273
+ * }
274
+ * ```
275
+ */
276
+ interface IgniterJobDefinition<TContext = unknown, TInput = unknown, TOutput = unknown> {
277
+ /**
278
+ * Input schema for validation (Zod or StandardSchemaV1 compatible).
279
+ * Optional but recommended for type safety and runtime validation.
280
+ */
281
+ input?: StandardSchemaV1<TInput>;
282
+ /**
283
+ * Retry configuration.
284
+ */
285
+ retry?: {
286
+ /**
287
+ * Maximum number of retry attempts.
288
+ * @default 3
289
+ */
290
+ attempts?: number;
291
+ /**
292
+ * Backoff strategy for retries.
293
+ * @default { type: 'exponential', delay: 1000 }
294
+ */
295
+ backoff?: IgniterJobBackoff;
296
+ };
297
+ /**
298
+ * Job timeout in milliseconds.
299
+ * Job will be failed if it doesn't complete within this time.
300
+ */
301
+ timeout?: number;
302
+ /**
303
+ * Job priority (higher = more important).
304
+ * @default 0
305
+ */
306
+ priority?: number;
307
+ /**
308
+ * Rate limiter configuration.
309
+ */
310
+ limiter?: IgniterJobLimiter;
311
+ /**
312
+ * Whether to remove job data on completion.
313
+ * @default false
314
+ */
315
+ removeOnComplete?: boolean | {
316
+ count?: number;
317
+ age?: number;
318
+ };
319
+ /**
320
+ * Whether to remove job data on failure.
321
+ * @default false
322
+ */
323
+ removeOnFail?: boolean | {
324
+ count?: number;
325
+ age?: number;
326
+ };
327
+ /**
328
+ * Job handler function.
329
+ */
330
+ handler: IgniterJobHandler<TContext, TInput, TOutput>;
331
+ /**
332
+ * Hook called when job fails (after all retries exhausted).
333
+ */
334
+ onFailure?: IgniterJobFailureHook<TContext, TInput>;
335
+ /**
336
+ * Hook called when job completes successfully.
337
+ */
338
+ onComplete?: IgniterJobCompleteHook<TContext, TInput, TOutput>;
339
+ }
340
+ /**
341
+ * Context passed to cron job handlers.
342
+ *
343
+ * @typeParam TContext - Application context type
344
+ */
345
+ interface IgniterCronHandlerContext<TContext> {
346
+ /**
347
+ * Application context provided during build.
348
+ */
349
+ context: TContext;
350
+ /**
351
+ * Cron job metadata.
352
+ */
353
+ cron: {
354
+ /**
355
+ * Cron job name.
356
+ */
357
+ name: string;
358
+ /**
359
+ * Queue name the cron belongs to.
360
+ */
361
+ queue: string;
362
+ /**
363
+ * Cron expression.
364
+ */
365
+ expression: string;
366
+ /**
367
+ * Timezone for the cron expression.
368
+ */
369
+ timezone?: string;
370
+ /**
371
+ * Unix timestamp when cron was triggered.
372
+ */
373
+ timestamp: number;
374
+ };
375
+ /**
376
+ * Log a message associated with this cron execution.
377
+ *
378
+ * @param level - Log level
379
+ * @param message - Message to log
380
+ */
381
+ log: (level: 'info' | 'warn' | 'error', message: string) => Promise<void>;
382
+ }
383
+ /**
384
+ * Cron handler function type.
385
+ *
386
+ * @typeParam TContext - Application context type
387
+ * @typeParam TOutput - Cron output type
388
+ */
389
+ type IgniterCronHandler<TContext, TOutput> = (ctx: IgniterCronHandlerContext<TContext>) => Promise<TOutput> | TOutput;
390
+ /**
391
+ * Hook called when a cron job fails.
392
+ */
393
+ type IgniterCronFailureHook<TContext> = (ctx: IgniterCronHandlerContext<TContext>, error: Error) => void | Promise<void>;
394
+ /**
395
+ * Full cron job definition.
396
+ *
397
+ * @typeParam TContext - Application context type
398
+ * @typeParam TOutput - Cron output type
399
+ *
400
+ * @example
401
+ * ```typescript
402
+ * const dailyCleanup: IgniterCronDefinition<AppContext, void> = {
403
+ * expression: '0 0 * * *', // Every day at midnight
404
+ * timezone: 'America/New_York',
405
+ * handler: async (ctx) => {
406
+ * await ctx.context.db.cleanup.expiredSessions()
407
+ * ctx.log('info', 'Cleaned up expired sessions')
408
+ * },
409
+ * }
410
+ * ```
411
+ */
412
+ interface IgniterCronDefinition<TContext = unknown, TOutput = unknown> {
413
+ /**
414
+ * Cron expression (standard cron format).
415
+ *
416
+ * @example '0 0 * * *' // Every day at midnight
417
+ * @example '/5 * * * *' // Every 5 minutes
418
+ * @example '0 9 * * 1' // Every Monday at 9 AM
419
+ */
420
+ expression: string;
421
+ /**
422
+ * Timezone for the cron expression.
423
+ * @default 'UTC'
424
+ *
425
+ * @example 'America/New_York'
426
+ * @example 'Europe/London'
427
+ */
428
+ timezone?: string;
429
+ /**
430
+ * Whether to run immediately on startup (in addition to the cron schedule).
431
+ * @default false
432
+ */
433
+ runOnStart?: boolean;
434
+ /**
435
+ * Whether to skip if the previous run is still executing.
436
+ * @default true
437
+ */
438
+ skipIfRunning?: boolean;
439
+ /**
440
+ * Job timeout in milliseconds.
441
+ */
442
+ timeout?: number;
443
+ /**
444
+ * Cron handler function.
445
+ */
446
+ handler: IgniterCronHandler<TContext, TOutput>;
447
+ /**
448
+ * Hook called when cron job fails.
449
+ */
450
+ onFailure?: IgniterCronFailureHook<TContext>;
451
+ }
452
+ /**
453
+ * Job information returned from management APIs.
454
+ */
455
+ interface IgniterJobInfo {
456
+ /**
457
+ * Unique job ID.
458
+ */
459
+ id: string;
460
+ /**
461
+ * Job name.
462
+ */
463
+ name: string;
464
+ /**
465
+ * Queue name.
466
+ */
467
+ queue: string;
468
+ /**
469
+ * Current job state.
470
+ */
471
+ state: IgniterJobStatus;
472
+ /**
473
+ * Job input data.
474
+ */
475
+ data: unknown;
476
+ /**
477
+ * Job result (if completed).
478
+ */
479
+ result?: unknown;
480
+ /**
481
+ * Error message (if failed).
482
+ */
483
+ error?: string;
484
+ /**
485
+ * Job progress (0-100).
486
+ */
487
+ progress?: number;
488
+ /**
489
+ * Number of attempts made.
490
+ */
491
+ attempts: number;
492
+ /**
493
+ * Unix timestamp when job was created.
494
+ */
495
+ timestamp: number;
496
+ /**
497
+ * Unix timestamp when job processing started.
498
+ */
499
+ processedOn?: number;
500
+ /**
501
+ * Unix timestamp when job finished (completed or failed).
502
+ */
503
+ finishedOn?: number;
504
+ /**
505
+ * Job delay in milliseconds (if delayed).
506
+ */
507
+ delay?: number;
508
+ /**
509
+ * Job priority.
510
+ */
511
+ priority?: number;
512
+ /**
513
+ * Scope entry attached to the job.
514
+ */
515
+ scope?: IgniterJobScopeEntry;
516
+ /**
517
+ * Actor entry attached to the job.
518
+ */
519
+ actor?: IgniterJobActorEntry;
520
+ /**
521
+ * Additional metadata.
522
+ */
523
+ metadata?: Record<string, unknown>;
524
+ }
525
+ /**
526
+ * Possible job states.
527
+ */
528
+ type IgniterJobStatus = 'waiting' | 'active' | 'completed' | 'failed' | 'delayed' | 'paused';
529
+ /**
530
+ * Job counts per state.
531
+ */
532
+ interface IgniterJobCounts {
533
+ waiting: number;
534
+ active: number;
535
+ completed: number;
536
+ failed: number;
537
+ delayed: number;
538
+ paused: number;
539
+ }
540
+ /**
541
+ * Job log entry.
542
+ */
543
+ interface IgniterJobLog {
544
+ /**
545
+ * Log timestamp.
546
+ */
547
+ timestamp: Date;
548
+ /**
549
+ * Log message.
550
+ */
551
+ message: string;
552
+ /**
553
+ * Log level.
554
+ */
555
+ level: 'info' | 'warn' | 'error';
556
+ }
557
+
558
+ /**
559
+ * @fileoverview Queue types for @igniter-js/jobs
560
+ * @module @igniter-js/jobs/types/queue
561
+ */
562
+
563
+ /**
564
+ * Queue configuration for building.
565
+ *
566
+ * @typeParam TContext - Application context type
567
+ * @typeParam TJobs - Map of job names to definitions
568
+ * @typeParam TCrons - Map of cron names to definitions
569
+ */
570
+ interface IgniterQueueConfig<TContext, TJobs extends Record<string, IgniterJobDefinition<TContext, any, any>>, TCrons extends Record<string, IgniterCronDefinition<TContext, any>> = Record<string, never>> {
571
+ /**
572
+ * Queue name (will be prefixed with 'igniter:jobs:').
573
+ */
574
+ name: string;
575
+ /**
576
+ * Job definitions for this queue.
577
+ */
578
+ jobs: TJobs;
579
+ /**
580
+ * Cron definitions for this queue.
581
+ */
582
+ crons: TCrons;
583
+ }
584
+ /**
585
+ * Queue information returned from management APIs.
586
+ */
587
+ interface IgniterQueueInfo {
588
+ /**
589
+ * Queue name.
590
+ */
591
+ name: string;
592
+ /**
593
+ * Whether the queue is currently paused.
594
+ */
595
+ isPaused: boolean;
596
+ /**
597
+ * Job counts per state.
598
+ */
599
+ jobCounts: IgniterJobCounts;
600
+ }
601
+ /**
602
+ * Options for cleaning jobs from a queue.
603
+ */
604
+ interface IgniterQueueCleanOptions {
605
+ /**
606
+ * Job status(es) to clean.
607
+ */
608
+ status: 'completed' | 'failed' | 'delayed' | 'waiting' | 'active' | Array<'completed' | 'failed' | 'delayed' | 'waiting' | 'active'>;
609
+ /**
610
+ * Only clean jobs older than this many milliseconds.
611
+ * @default 0 (clean all matching jobs)
612
+ */
613
+ olderThan?: number;
614
+ /**
615
+ * Maximum number of jobs to clean.
616
+ * @default 1000
617
+ */
618
+ limit?: number;
619
+ }
620
+ /**
621
+ * Search filter for queues.
622
+ */
623
+ interface IgniterQueuesSearchFilter {
624
+ /**
625
+ * Filter by queue name (partial match).
626
+ */
627
+ name?: string;
628
+ /**
629
+ * Filter by paused state.
630
+ */
631
+ isPaused?: boolean;
632
+ }
633
+ /**
634
+ * Search filter for jobs.
635
+ */
636
+ interface IgniterJobsSearchFilter {
637
+ /**
638
+ * Filter by job status(es).
639
+ */
640
+ status?: Array<'waiting' | 'active' | 'completed' | 'failed' | 'delayed' | 'paused'>;
641
+ /**
642
+ * Filter by queue name.
643
+ */
644
+ queue?: string;
645
+ /**
646
+ * Filter by job name.
647
+ */
648
+ jobName?: string;
649
+ /**
650
+ * Filter by scope ID.
651
+ */
652
+ scopeId?: string;
653
+ /**
654
+ * Filter by actor ID.
655
+ */
656
+ actorId?: string;
657
+ /**
658
+ * Filter by date range.
659
+ */
660
+ dateRange?: {
661
+ from?: Date;
662
+ to?: Date;
663
+ };
664
+ /**
665
+ * Order results.
666
+ */
667
+ orderBy?: 'createdAt:asc' | 'createdAt:desc' | 'priority:asc' | 'priority:desc';
668
+ /**
669
+ * Maximum number of results.
670
+ * @default 100
671
+ */
672
+ limit?: number;
673
+ /**
674
+ * Offset for pagination.
675
+ * @default 0
676
+ */
677
+ offset?: number;
678
+ }
679
+ /**
680
+ * Search filter for workers.
681
+ */
682
+ interface IgniterWorkersSearchFilter {
683
+ /**
684
+ * Filter by queue name.
685
+ */
686
+ queue?: string;
687
+ /**
688
+ * Filter by running state.
689
+ */
690
+ isRunning?: boolean;
691
+ }
692
+ /**
693
+ * Search result for jobs.
694
+ */
695
+ interface IgniterJobSearchResult {
696
+ /**
697
+ * Job ID.
698
+ */
699
+ id: string;
700
+ /**
701
+ * Job name.
702
+ */
703
+ name: string;
704
+ /**
705
+ * Queue name.
706
+ */
707
+ queue: string;
708
+ /**
709
+ * Job state.
710
+ */
711
+ state: 'waiting' | 'active' | 'completed' | 'failed' | 'delayed' | 'paused';
712
+ /**
713
+ * Job data (input).
714
+ */
715
+ data: unknown;
716
+ /**
717
+ * Job result (if completed).
718
+ */
719
+ result?: unknown;
720
+ /**
721
+ * Error message (if failed).
722
+ */
723
+ error?: string;
724
+ /**
725
+ * Job progress (0-100).
726
+ */
727
+ progress?: number;
728
+ /**
729
+ * Attempt count.
730
+ */
731
+ attempts: number;
732
+ /**
733
+ * Creation timestamp.
734
+ */
735
+ timestamp: number;
736
+ /**
737
+ * Processing start timestamp.
738
+ */
739
+ processedOn?: number;
740
+ /**
741
+ * Finish timestamp.
742
+ */
743
+ finishedOn?: number;
744
+ /**
745
+ * Scope entry.
746
+ */
747
+ scope?: {
748
+ id: string;
749
+ tags?: Record<string, string | number | boolean>;
750
+ };
751
+ /**
752
+ * Actor entry.
753
+ */
754
+ actor?: {
755
+ id?: string;
756
+ tags?: Record<string, string | number | boolean>;
757
+ };
758
+ }
759
+
760
+ /**
761
+ * @fileoverview Event types for @igniter-js/jobs (subscribe pattern)
762
+ * @module @igniter-js/jobs/types/events
763
+ */
764
+
765
+ /**
766
+ * Job lifecycle event types.
767
+ */
768
+ type IgniterJobEventType = 'enqueued' | 'started' | 'progress' | 'completed' | 'failed' | 'retrying';
769
+ /**
770
+ * Base event context passed to subscribers.
771
+ *
772
+ * @typeParam TEventType - Full event type string
773
+ * @typeParam TPayload - Event payload type
774
+ */
775
+ interface IgniterJobEventContext<TEventType extends string = string, TPayload = unknown> {
776
+ /**
777
+ * Full event type (e.g., 'email:sendWelcome:completed').
778
+ */
779
+ type: TEventType;
780
+ /**
781
+ * Event payload data.
782
+ */
783
+ data: TPayload;
784
+ /**
785
+ * ISO timestamp when the event occurred.
786
+ */
787
+ timestamp: string;
788
+ /**
789
+ * Scope entry if the job had one.
790
+ */
791
+ scope?: IgniterJobScopeEntry;
792
+ /**
793
+ * Actor entry if the job had one.
794
+ */
795
+ actor?: IgniterJobActorEntry;
796
+ }
797
+ /**
798
+ * Unsubscribe function returned from subscribe.
799
+ */
800
+ type IgniterJobUnsubscribeFn = () => Promise<void>;
801
+ /**
802
+ * Event handler function.
803
+ *
804
+ * @typeParam TContext - Event context type
805
+ */
806
+ type IgniterJobEventHandler<TContext = IgniterJobEventContext> = (ctx: TContext) => void | Promise<void>;
807
+ /**
808
+ * Payload for 'enqueued' events.
809
+ *
810
+ * @typeParam TInput - Job input type
811
+ */
812
+ interface IgniterJobEnqueuedPayload<TInput = unknown> {
813
+ /**
814
+ * Unique job ID.
815
+ */
816
+ jobId: string;
817
+ /**
818
+ * Job name.
819
+ */
820
+ name: string;
821
+ /**
822
+ * Queue name.
823
+ */
824
+ queue: string;
825
+ /**
826
+ * Job input data.
827
+ */
828
+ data: TInput;
829
+ /**
830
+ * ISO timestamp when job was enqueued.
831
+ */
832
+ enqueuedAt: string;
833
+ }
834
+ /**
835
+ * Payload for 'started' events.
836
+ */
837
+ interface IgniterJobStartedPayload {
838
+ /**
839
+ * Unique job ID.
840
+ */
841
+ jobId: string;
842
+ /**
843
+ * Job name.
844
+ */
845
+ name: string;
846
+ /**
847
+ * Queue name.
848
+ */
849
+ queue: string;
850
+ /**
851
+ * Current attempt number.
852
+ */
853
+ attempt: number;
854
+ /**
855
+ * ISO timestamp when job started.
856
+ */
857
+ startedAt: string;
858
+ }
859
+ /**
860
+ * Payload for 'progress' events.
861
+ */
862
+ interface IgniterJobProgressPayload {
863
+ /**
864
+ * Unique job ID.
865
+ */
866
+ jobId: string;
867
+ /**
868
+ * Job name.
869
+ */
870
+ name: string;
871
+ /**
872
+ * Queue name.
873
+ */
874
+ queue: string;
875
+ /**
876
+ * Progress percentage (0-100).
877
+ */
878
+ progress: number;
879
+ /**
880
+ * ISO timestamp.
881
+ */
882
+ timestamp: string;
883
+ }
884
+ /**
885
+ * Payload for 'completed' events.
886
+ *
887
+ * @typeParam TResult - Job result type
888
+ */
889
+ interface IgniterJobCompletedPayload<TResult = unknown> {
890
+ /**
891
+ * Unique job ID.
892
+ */
893
+ jobId: string;
894
+ /**
895
+ * Job name.
896
+ */
897
+ name: string;
898
+ /**
899
+ * Queue name.
900
+ */
901
+ queue: string;
902
+ /**
903
+ * Job result.
904
+ */
905
+ result: TResult;
906
+ /**
907
+ * Execution duration in milliseconds.
908
+ */
909
+ duration: number;
910
+ /**
911
+ * ISO timestamp when job completed.
912
+ */
913
+ completedAt: string;
914
+ }
915
+ /**
916
+ * Payload for 'failed' events.
917
+ */
918
+ interface IgniterJobFailedPayload {
919
+ /**
920
+ * Unique job ID.
921
+ */
922
+ jobId: string;
923
+ /**
924
+ * Job name.
925
+ */
926
+ name: string;
927
+ /**
928
+ * Queue name.
929
+ */
930
+ queue: string;
931
+ /**
932
+ * Error message.
933
+ */
934
+ error: string;
935
+ /**
936
+ * Error stack trace (if available).
937
+ */
938
+ stack?: string;
939
+ /**
940
+ * Attempt number when failure occurred.
941
+ */
942
+ attempt: number;
943
+ /**
944
+ * Whether more retries are available.
945
+ */
946
+ retriesLeft: number;
947
+ /**
948
+ * ISO timestamp when job failed.
949
+ */
950
+ failedAt: string;
951
+ }
952
+ /**
953
+ * Payload for 'retrying' events.
954
+ */
955
+ interface IgniterJobRetryingPayload {
956
+ /**
957
+ * Unique job ID.
958
+ */
959
+ jobId: string;
960
+ /**
961
+ * Job name.
962
+ */
963
+ name: string;
964
+ /**
965
+ * Queue name.
966
+ */
967
+ queue: string;
968
+ /**
969
+ * Previous error message.
970
+ */
971
+ error: string;
972
+ /**
973
+ * Attempt number being retried.
974
+ */
975
+ attempt: number;
976
+ /**
977
+ * Delay before next attempt in milliseconds.
978
+ */
979
+ delay: number;
980
+ /**
981
+ * ISO timestamp.
982
+ */
983
+ retryingAt: string;
984
+ }
985
+ /**
986
+ * Union of all event payloads.
987
+ */
988
+ type IgniterJobEventPayload = IgniterJobEnqueuedPayload | IgniterJobStartedPayload | IgniterJobProgressPayload | IgniterJobCompletedPayload | IgniterJobFailedPayload | IgniterJobRetryingPayload;
989
+
990
+ /**
991
+ * @fileoverview Adapter interface for @igniter-js/jobs
992
+ * @module @igniter-js/jobs/types/adapter
993
+ */
994
+
995
+ /**
996
+ * Parameters for dispatching a job.
997
+ */
998
+ interface AdapterDispatchParams {
999
+ /**
1000
+ * Queue name.
1001
+ */
1002
+ queue: string;
1003
+ /**
1004
+ * Job name.
1005
+ */
1006
+ name: string;
1007
+ /**
1008
+ * Job input data.
1009
+ */
1010
+ data: unknown;
1011
+ /**
1012
+ * Custom job ID (optional).
1013
+ */
1014
+ jobId?: string;
1015
+ /**
1016
+ * Delay before processing in milliseconds.
1017
+ */
1018
+ delay?: number;
1019
+ /**
1020
+ * Job priority.
1021
+ */
1022
+ priority?: number;
1023
+ /**
1024
+ * Max retry attempts.
1025
+ */
1026
+ attempts?: number;
1027
+ /**
1028
+ * Backoff configuration.
1029
+ */
1030
+ backoff?: {
1031
+ type: 'exponential' | 'fixed' | 'linear';
1032
+ delay: number;
1033
+ maxDelay?: number;
1034
+ } | {
1035
+ type: 'custom';
1036
+ delays: number[];
1037
+ };
1038
+ /**
1039
+ * Remove on completion config.
1040
+ */
1041
+ removeOnComplete?: boolean | {
1042
+ count?: number;
1043
+ age?: number;
1044
+ };
1045
+ /**
1046
+ * Remove on failure config.
1047
+ */
1048
+ removeOnFail?: boolean | {
1049
+ count?: number;
1050
+ age?: number;
1051
+ };
1052
+ /**
1053
+ * Scope entry.
1054
+ */
1055
+ scope?: IgniterJobScopeEntry;
1056
+ /**
1057
+ * Actor entry.
1058
+ */
1059
+ actor?: IgniterJobActorEntry;
1060
+ }
1061
+ /**
1062
+ * Parameters for scheduling a job (delayed or cron).
1063
+ */
1064
+ interface AdapterScheduleParams extends AdapterDispatchParams {
1065
+ /**
1066
+ * Schedule job at this specific time.
1067
+ */
1068
+ at?: Date;
1069
+ /**
1070
+ * Cron expression for repeating jobs.
1071
+ */
1072
+ cron?: string;
1073
+ /**
1074
+ * Repeat every N milliseconds.
1075
+ */
1076
+ every?: number;
1077
+ /**
1078
+ * Timezone for cron expression.
1079
+ */
1080
+ timezone?: string;
1081
+ }
1082
+ /**
1083
+ * Worker configuration for the adapter.
1084
+ */
1085
+ interface AdapterWorkerConfig {
1086
+ /**
1087
+ * Queue names to process.
1088
+ */
1089
+ queues: string[];
1090
+ /**
1091
+ * Concurrency per queue.
1092
+ */
1093
+ concurrency: number;
1094
+ /**
1095
+ * Rate limiter config.
1096
+ */
1097
+ limiter?: {
1098
+ max: number;
1099
+ duration: number;
1100
+ };
1101
+ /**
1102
+ * Lock duration in milliseconds.
1103
+ */
1104
+ lockDuration?: number;
1105
+ /**
1106
+ * Callback when worker becomes idle.
1107
+ */
1108
+ onIdle?: () => void;
1109
+ }
1110
+ /**
1111
+ * Worker handle returned by adapter.
1112
+ */
1113
+ interface AdapterWorkerHandle {
1114
+ /**
1115
+ * Worker ID.
1116
+ */
1117
+ id: string;
1118
+ /**
1119
+ * Pause the worker.
1120
+ */
1121
+ pause(): Promise<void>;
1122
+ /**
1123
+ * Resume the worker.
1124
+ */
1125
+ resume(): Promise<void>;
1126
+ /**
1127
+ * Close the worker.
1128
+ */
1129
+ close(): Promise<void>;
1130
+ /**
1131
+ * Check if worker is running.
1132
+ */
1133
+ isRunning(): boolean;
1134
+ /**
1135
+ * Check if worker is paused.
1136
+ */
1137
+ isPaused(): boolean;
1138
+ /**
1139
+ * Get worker metrics.
1140
+ */
1141
+ getMetrics(): Promise<{
1142
+ processed: number;
1143
+ failed: number;
1144
+ completed: number;
1145
+ active: number;
1146
+ uptime: number;
1147
+ }>;
1148
+ }
1149
+ /**
1150
+ * Job handler for adapter workers.
1151
+ */
1152
+ type AdapterJobHandler = (job: {
1153
+ id: string;
1154
+ name: string;
1155
+ queue: string;
1156
+ data: unknown;
1157
+ attempt: number;
1158
+ timestamp: number;
1159
+ scope?: IgniterJobScopeEntry;
1160
+ actor?: IgniterJobActorEntry;
1161
+ log: (level: 'info' | 'warn' | 'error', message: string) => Promise<void>;
1162
+ updateProgress: (progress: number) => Promise<void>;
1163
+ }) => Promise<unknown>;
1164
+ /**
1165
+ * Adapter interface for job queue backends.
1166
+ *
1167
+ * Implementations must provide all methods for:
1168
+ * - Job dispatching and scheduling
1169
+ * - Queue management
1170
+ * - Job management
1171
+ * - Event subscriptions
1172
+ * - Worker creation
1173
+ *
1174
+ * @example
1175
+ * ```typescript
1176
+ * class BullMQAdapter implements IgniterJobsAdapter {
1177
+ * // Implementation
1178
+ * }
1179
+ * ```
1180
+ */
1181
+ interface IgniterJobsAdapter {
1182
+ /**
1183
+ * Underlying client reference (e.g., Redis instance).
1184
+ */
1185
+ readonly client: unknown;
1186
+ /**
1187
+ * Dispatch a job for immediate processing.
1188
+ *
1189
+ * @param params - Job dispatch parameters
1190
+ * @returns Job ID
1191
+ */
1192
+ dispatch(params: AdapterDispatchParams): Promise<string>;
1193
+ /**
1194
+ * Schedule a job for future processing.
1195
+ *
1196
+ * @param params - Job schedule parameters
1197
+ * @returns Job ID
1198
+ */
1199
+ schedule(params: AdapterScheduleParams): Promise<string>;
1200
+ /**
1201
+ * Get job information by ID.
1202
+ *
1203
+ * @param queue - Queue name
1204
+ * @param jobId - Job ID
1205
+ * @returns Job info or null if not found
1206
+ */
1207
+ getJob(queue: string, jobId: string): Promise<IgniterJobInfo | null>;
1208
+ /**
1209
+ * Get job state.
1210
+ *
1211
+ * @param queue - Queue name
1212
+ * @param jobId - Job ID
1213
+ * @returns Job status
1214
+ */
1215
+ getJobState(queue: string, jobId: string): Promise<IgniterJobStatus | null>;
1216
+ /**
1217
+ * Get job progress.
1218
+ *
1219
+ * @param queue - Queue name
1220
+ * @param jobId - Job ID
1221
+ * @returns Progress (0-100)
1222
+ */
1223
+ getJobProgress(queue: string, jobId: string): Promise<number>;
1224
+ /**
1225
+ * Get job logs.
1226
+ *
1227
+ * @param queue - Queue name
1228
+ * @param jobId - Job ID
1229
+ * @returns Array of log entries
1230
+ */
1231
+ getJobLogs(queue: string, jobId: string): Promise<IgniterJobLog[]>;
1232
+ /**
1233
+ * Retry a failed job.
1234
+ *
1235
+ * @param queue - Queue name
1236
+ * @param jobId - Job ID
1237
+ */
1238
+ retryJob(queue: string, jobId: string): Promise<void>;
1239
+ /**
1240
+ * Remove a job.
1241
+ *
1242
+ * @param queue - Queue name
1243
+ * @param jobId - Job ID
1244
+ */
1245
+ removeJob(queue: string, jobId: string): Promise<void>;
1246
+ /**
1247
+ * Promote a delayed job to waiting.
1248
+ *
1249
+ * @param queue - Queue name
1250
+ * @param jobId - Job ID
1251
+ */
1252
+ promoteJob(queue: string, jobId: string): Promise<void>;
1253
+ /**
1254
+ * Move a job to a different state.
1255
+ *
1256
+ * @param queue - Queue name
1257
+ * @param jobId - Job ID
1258
+ * @param state - Target state
1259
+ * @param reason - Optional reason
1260
+ */
1261
+ moveJob(queue: string, jobId: string, state: 'failed' | 'completed', reason?: string): Promise<void>;
1262
+ /**
1263
+ * Retry multiple jobs.
1264
+ *
1265
+ * @param queue - Queue name
1266
+ * @param jobIds - Job IDs
1267
+ */
1268
+ retryJobs(queue: string, jobIds: string[]): Promise<void>;
1269
+ /**
1270
+ * Remove multiple jobs.
1271
+ *
1272
+ * @param queue - Queue name
1273
+ * @param jobIds - Job IDs
1274
+ */
1275
+ removeJobs(queue: string, jobIds: string[]): Promise<void>;
1276
+ /**
1277
+ * Get queue information.
1278
+ *
1279
+ * @param queue - Queue name
1280
+ * @returns Queue info
1281
+ */
1282
+ getQueue(queue: string): Promise<IgniterQueueInfo>;
1283
+ /**
1284
+ * Pause a queue.
1285
+ *
1286
+ * @param queue - Queue name
1287
+ */
1288
+ pauseQueue(queue: string): Promise<void>;
1289
+ /**
1290
+ * Resume a paused queue.
1291
+ *
1292
+ * @param queue - Queue name
1293
+ */
1294
+ resumeQueue(queue: string): Promise<void>;
1295
+ /**
1296
+ * Drain a queue (remove all waiting and delayed jobs).
1297
+ *
1298
+ * @param queue - Queue name
1299
+ * @returns Number of jobs removed
1300
+ */
1301
+ drainQueue(queue: string): Promise<number>;
1302
+ /**
1303
+ * Clean jobs from a queue.
1304
+ *
1305
+ * @param queue - Queue name
1306
+ * @param options - Clean options
1307
+ * @returns Number of jobs removed
1308
+ */
1309
+ cleanQueue(queue: string, options: IgniterQueueCleanOptions): Promise<number>;
1310
+ /**
1311
+ * Obliterate a queue (remove all data).
1312
+ *
1313
+ * @param queue - Queue name
1314
+ * @param options - Obliterate options
1315
+ */
1316
+ obliterateQueue(queue: string, options?: {
1317
+ force?: boolean;
1318
+ }): Promise<void>;
1319
+ /**
1320
+ * Retry all failed jobs in a queue.
1321
+ *
1322
+ * @param queue - Queue name
1323
+ * @returns Number of jobs retried
1324
+ */
1325
+ retryAllFailed(queue: string): Promise<number>;
1326
+ /**
1327
+ * Get job counts for a queue.
1328
+ *
1329
+ * @param queue - Queue name
1330
+ * @returns Job counts per state
1331
+ */
1332
+ getJobCounts(queue: string): Promise<IgniterJobCounts>;
1333
+ /**
1334
+ * List jobs in a queue.
1335
+ *
1336
+ * @param queue - Queue name
1337
+ * @param options - List options
1338
+ * @returns Array of job search results
1339
+ */
1340
+ listJobs(queue: string, options?: {
1341
+ status?: IgniterJobStatus[];
1342
+ start?: number;
1343
+ end?: number;
1344
+ }): Promise<IgniterJobSearchResult[]>;
1345
+ /**
1346
+ * Pause processing of a specific job type.
1347
+ *
1348
+ * @param queue - Queue name
1349
+ * @param jobName - Job name
1350
+ */
1351
+ pauseJobType(queue: string, jobName: string): Promise<void>;
1352
+ /**
1353
+ * Resume processing of a specific job type.
1354
+ *
1355
+ * @param queue - Queue name
1356
+ * @param jobName - Job name
1357
+ */
1358
+ resumeJobType(queue: string, jobName: string): Promise<void>;
1359
+ /**
1360
+ * Subscribe to job events.
1361
+ *
1362
+ * @param pattern - Event pattern (e.g., 'email:*', 'email:sendWelcome:*')
1363
+ * @param handler - Event handler
1364
+ * @returns Unsubscribe function
1365
+ */
1366
+ subscribe(pattern: string, handler: IgniterJobEventHandler): Promise<IgniterJobUnsubscribeFn>;
1367
+ /**
1368
+ * Create a worker.
1369
+ *
1370
+ * @param config - Worker configuration
1371
+ * @param handler - Job handler
1372
+ * @returns Worker handle
1373
+ */
1374
+ createWorker(config: AdapterWorkerConfig, handler: AdapterJobHandler): Promise<AdapterWorkerHandle>;
1375
+ /**
1376
+ * Search for jobs across queues.
1377
+ *
1378
+ * @param filter - Search filter
1379
+ * @returns Array of matching jobs
1380
+ */
1381
+ searchJobs(filter: {
1382
+ status?: IgniterJobStatus[];
1383
+ queue?: string;
1384
+ jobName?: string;
1385
+ scopeId?: string;
1386
+ actorId?: string;
1387
+ dateRange?: {
1388
+ from?: Date;
1389
+ to?: Date;
1390
+ };
1391
+ orderBy?: 'createdAt:asc' | 'createdAt:desc' | 'priority:asc' | 'priority:desc';
1392
+ limit?: number;
1393
+ offset?: number;
1394
+ }): Promise<IgniterJobSearchResult[]>;
1395
+ /**
1396
+ * Search for queues.
1397
+ *
1398
+ * @param filter - Search filter
1399
+ * @returns Array of queue info
1400
+ */
1401
+ searchQueues(filter: {
1402
+ name?: string;
1403
+ isPaused?: boolean;
1404
+ }): Promise<IgniterQueueInfo[]>;
1405
+ /**
1406
+ * Shutdown the adapter and clean up resources.
1407
+ */
1408
+ shutdown(): Promise<void>;
1409
+ }
1410
+
1411
+ export type { AdapterDispatchParams as A, IgniterJobLimiter as B, IgniterQueuesSearchFilter as C, IgniterJobsSearchFilter as D, IgniterWorkersSearchFilter as E, IgniterJobEventType as F, IgniterJobEventContext as G, IgniterJobEventPayload as H, IgniterJobsAdapter as I, IgniterJobEnqueuedPayload as J, IgniterJobStartedPayload as K, IgniterJobProgressPayload as L, IgniterJobCompletedPayload as M, IgniterJobFailedPayload as N, IgniterJobRetryingPayload as O, IgniterJobScopeEntry as P, IgniterJobActorEntry as Q, AdapterScheduleParams as a, IgniterJobInfo as b, IgniterJobStatus as c, IgniterJobLog as d, IgniterQueueInfo as e, IgniterQueueCleanOptions as f, IgniterJobCounts as g, IgniterJobSearchResult as h, IgniterJobEventHandler as i, IgniterJobUnsubscribeFn as j, AdapterWorkerConfig as k, AdapterJobHandler as l, AdapterWorkerHandle as m, IgniterJobDefinition as n, IgniterCronDefinition as o, IgniterQueueConfig as p, IgniterJobScopeOptions as q, IgniterJobActorOptions as r, IgniterJobHandler as s, IgniterJobHandlerContext as t, IgniterCronHandler as u, IgniterCronHandlerContext as v, IgniterJobFailureHook as w, IgniterJobCompleteHook as x, IgniterCronFailureHook as y, IgniterJobBackoff as z };