@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.
- package/AGENTS.md +557 -0
- package/README.md +410 -0
- package/dist/adapter-CcQCatSa.d.mts +1411 -0
- package/dist/adapter-CcQCatSa.d.ts +1411 -0
- package/dist/adapters/bullmq.adapter.d.mts +131 -0
- package/dist/adapters/bullmq.adapter.d.ts +131 -0
- package/dist/adapters/bullmq.adapter.js +598 -0
- package/dist/adapters/bullmq.adapter.js.map +1 -0
- package/dist/adapters/bullmq.adapter.mjs +596 -0
- package/dist/adapters/bullmq.adapter.mjs.map +1 -0
- package/dist/adapters/index.d.mts +5 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.js +1129 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/index.mjs +1126 -0
- package/dist/adapters/index.mjs.map +1 -0
- package/dist/adapters/memory.adapter.d.mts +118 -0
- package/dist/adapters/memory.adapter.d.ts +118 -0
- package/dist/adapters/memory.adapter.js +571 -0
- package/dist/adapters/memory.adapter.js.map +1 -0
- package/dist/adapters/memory.adapter.mjs +569 -0
- package/dist/adapters/memory.adapter.mjs.map +1 -0
- package/dist/index.d.mts +1107 -0
- package/dist/index.d.ts +1107 -0
- package/dist/index.js +1137 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1128 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +93 -0
|
@@ -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 };
|