qwerk 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/LICENSE +21 -0
- package/README.md +380 -0
- package/dist/index.d.ts +744 -0
- package/dist/index.js +1739 -0
- package/package.json +70 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,744 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Job status
|
|
3
|
+
*/
|
|
4
|
+
type JobStatus = "waiting" | "active" | "completed" | "failed" | "delayed" | "stalled";
|
|
5
|
+
/**
|
|
6
|
+
* Logger interface - implement this to use your own logger
|
|
7
|
+
*/
|
|
8
|
+
interface Logger {
|
|
9
|
+
debug(message: string, ...args: unknown[]): void;
|
|
10
|
+
info(message: string, ...args: unknown[]): void;
|
|
11
|
+
warn(message: string, ...args: unknown[]): void;
|
|
12
|
+
error(message: string, ...args: unknown[]): void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Default console logger
|
|
16
|
+
*/
|
|
17
|
+
declare const consoleLogger: Logger;
|
|
18
|
+
/**
|
|
19
|
+
* Silent logger (no output)
|
|
20
|
+
*/
|
|
21
|
+
declare const silentLogger: Logger;
|
|
22
|
+
/**
|
|
23
|
+
* Represents a job in the queue
|
|
24
|
+
*/
|
|
25
|
+
interface Job<
|
|
26
|
+
T = unknown,
|
|
27
|
+
R = unknown
|
|
28
|
+
> {
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly data: T;
|
|
32
|
+
readonly attempts: number;
|
|
33
|
+
readonly maxAttempts: number;
|
|
34
|
+
readonly createdAt: number;
|
|
35
|
+
readonly scheduledAt: number;
|
|
36
|
+
readonly backoff: BackoffOptions;
|
|
37
|
+
/** When the job started processing (set by pop) */
|
|
38
|
+
readonly startedAt?: number;
|
|
39
|
+
/** Job priority (lower = higher priority, default: 0) */
|
|
40
|
+
readonly priority: number;
|
|
41
|
+
/** Job timeout in ms (default: 30000) */
|
|
42
|
+
readonly timeout: number;
|
|
43
|
+
/** Repeat configuration for recurring jobs */
|
|
44
|
+
readonly repeat?: RepeatOptions;
|
|
45
|
+
/** Current progress (0-100) */
|
|
46
|
+
readonly progress?: number;
|
|
47
|
+
/** Job result (set after completion) */
|
|
48
|
+
readonly result?: R;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Options for creating a new job
|
|
52
|
+
*/
|
|
53
|
+
interface JobOptions {
|
|
54
|
+
/** Maximum retry attempts (default: 3) */
|
|
55
|
+
maxAttempts?: number;
|
|
56
|
+
/** Delay before first execution in ms (default: 0) */
|
|
57
|
+
delay?: number;
|
|
58
|
+
/** Backoff strategy for retries */
|
|
59
|
+
backoff?: BackoffOptions;
|
|
60
|
+
/** Job priority - lower number = higher priority (default: 0) */
|
|
61
|
+
priority?: number;
|
|
62
|
+
/** Job timeout in ms - job fails if handler exceeds this (default: 30000) */
|
|
63
|
+
timeout?: number;
|
|
64
|
+
/** Unique job ID - if provided, prevents duplicate jobs with same ID */
|
|
65
|
+
jobId?: string;
|
|
66
|
+
/** Repeat configuration for recurring jobs */
|
|
67
|
+
repeat?: RepeatOptions;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Configuration for repeatable/recurring jobs
|
|
71
|
+
*/
|
|
72
|
+
interface RepeatOptions {
|
|
73
|
+
/** Cron expression (e.g., "0 * * * *" for every hour) */
|
|
74
|
+
cron?: string;
|
|
75
|
+
/** Fixed interval in ms between job completions */
|
|
76
|
+
every?: number;
|
|
77
|
+
/** Maximum number of times to repeat (undefined = infinite) */
|
|
78
|
+
limit?: number;
|
|
79
|
+
/** Number of times this job has been repeated */
|
|
80
|
+
count?: number;
|
|
81
|
+
/** Unique key for this repeatable job (auto-generated if not provided) */
|
|
82
|
+
key?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Backoff configuration for retries
|
|
86
|
+
*/
|
|
87
|
+
interface BackoffOptions {
|
|
88
|
+
type: "exponential" | "linear" | "fixed";
|
|
89
|
+
/** Base delay in ms (default: 1000) */
|
|
90
|
+
delay: number;
|
|
91
|
+
/** Maximum delay in ms (default: 30000) */
|
|
92
|
+
maxDelay?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Context passed to job handlers for progress updates and signals
|
|
96
|
+
*/
|
|
97
|
+
interface JobContext {
|
|
98
|
+
/** Update job progress (0-100) */
|
|
99
|
+
updateProgress(progress: number): Promise<void>;
|
|
100
|
+
/** AbortSignal for cancellation */
|
|
101
|
+
signal: AbortSignal;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Backend interface - implement this for custom storage
|
|
105
|
+
*/
|
|
106
|
+
interface Backend {
|
|
107
|
+
/**
|
|
108
|
+
* Add a job to the queue
|
|
109
|
+
* @returns false if job with same ID already exists (deduplication)
|
|
110
|
+
*/
|
|
111
|
+
push(job: Job): Promise<boolean>;
|
|
112
|
+
/**
|
|
113
|
+
* Add multiple jobs to the queue (bulk operation)
|
|
114
|
+
* @returns number of jobs successfully added
|
|
115
|
+
*/
|
|
116
|
+
pushBulk(jobs: Job[]): Promise<number>;
|
|
117
|
+
/**
|
|
118
|
+
* Get the next job ready for processing (atomic)
|
|
119
|
+
* Moves job to "active" state with visibility timeout
|
|
120
|
+
*/
|
|
121
|
+
pop(visibilityTimeout: number): Promise<Job | null>;
|
|
122
|
+
/**
|
|
123
|
+
* Acknowledge successful job completion
|
|
124
|
+
* Removes job from active set and stores result
|
|
125
|
+
*/
|
|
126
|
+
ack(jobId: string, result?: unknown): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* Negative acknowledge - reschedule job for retry
|
|
129
|
+
*/
|
|
130
|
+
nack(job: Job, nextAttemptAt: number): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Move a job to the dead letter queue
|
|
133
|
+
*/
|
|
134
|
+
fail(job: Job, error: Error): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Get stalled jobs (exceeded visibility timeout)
|
|
137
|
+
* These should be moved back to waiting or failed
|
|
138
|
+
*/
|
|
139
|
+
getStalled(): Promise<Job[]>;
|
|
140
|
+
/**
|
|
141
|
+
* Update job progress (0-100)
|
|
142
|
+
*/
|
|
143
|
+
updateProgress(jobId: string, progress: number): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* Get a completed job with its result
|
|
146
|
+
*/
|
|
147
|
+
getCompleted(jobId: string): Promise<{
|
|
148
|
+
job: Job;
|
|
149
|
+
result: unknown;
|
|
150
|
+
completedAt: number;
|
|
151
|
+
} | null>;
|
|
152
|
+
/**
|
|
153
|
+
* Get completed jobs count
|
|
154
|
+
*/
|
|
155
|
+
completedCount(): Promise<number>;
|
|
156
|
+
/**
|
|
157
|
+
* Get recent completed jobs
|
|
158
|
+
*/
|
|
159
|
+
getCompletedJobs(limit?: number): Promise<Array<{
|
|
160
|
+
job: Job;
|
|
161
|
+
result: unknown;
|
|
162
|
+
completedAt: number;
|
|
163
|
+
}>>;
|
|
164
|
+
/**
|
|
165
|
+
* Subscribe to job notifications (for real-time processing)
|
|
166
|
+
*/
|
|
167
|
+
subscribe(callback: () => void): void;
|
|
168
|
+
/**
|
|
169
|
+
* Unsubscribe from notifications
|
|
170
|
+
*/
|
|
171
|
+
unsubscribe(): void;
|
|
172
|
+
/**
|
|
173
|
+
* Get queue size (pending jobs)
|
|
174
|
+
*/
|
|
175
|
+
size(): Promise<number>;
|
|
176
|
+
/**
|
|
177
|
+
* Get count of active (processing) jobs
|
|
178
|
+
*/
|
|
179
|
+
activeCount(): Promise<number>;
|
|
180
|
+
/**
|
|
181
|
+
* Get count of failed jobs in DLQ
|
|
182
|
+
*/
|
|
183
|
+
failedCount(): Promise<number>;
|
|
184
|
+
/**
|
|
185
|
+
* Get failed jobs from DLQ
|
|
186
|
+
*/
|
|
187
|
+
getFailed(limit?: number): Promise<Array<{
|
|
188
|
+
job: Job;
|
|
189
|
+
error: string;
|
|
190
|
+
failedAt: number;
|
|
191
|
+
}>>;
|
|
192
|
+
/**
|
|
193
|
+
* Retry a failed job (move from DLQ back to queue)
|
|
194
|
+
*/
|
|
195
|
+
retryFailed(jobId: string): Promise<boolean>;
|
|
196
|
+
/**
|
|
197
|
+
* Remove a job by ID (from any state)
|
|
198
|
+
*/
|
|
199
|
+
remove(jobId: string): Promise<boolean>;
|
|
200
|
+
/**
|
|
201
|
+
* Clear all jobs (waiting, active, failed)
|
|
202
|
+
*/
|
|
203
|
+
clear(): Promise<void>;
|
|
204
|
+
/**
|
|
205
|
+
* Close/cleanup resources
|
|
206
|
+
*/
|
|
207
|
+
close?(): Promise<void>;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Queue events
|
|
211
|
+
*/
|
|
212
|
+
interface QueueEvents<
|
|
213
|
+
T = unknown,
|
|
214
|
+
R = unknown
|
|
215
|
+
> {
|
|
216
|
+
/** Job completed successfully */
|
|
217
|
+
completed: (job: Job<T, R>, result: R | undefined) => void;
|
|
218
|
+
/** Job failed after all retries (moved to DLQ) */
|
|
219
|
+
failed: (job: Job<T, R>, error: Error) => void;
|
|
220
|
+
/** Job failed, will retry */
|
|
221
|
+
retry: (job: Job<T, R>, error: Error) => void;
|
|
222
|
+
/** Job exceeded visibility timeout, will be reprocessed */
|
|
223
|
+
stalled: (job: Job<T, R>) => void;
|
|
224
|
+
/** Job timed out during processing */
|
|
225
|
+
timeout: (job: Job<T, R>) => void;
|
|
226
|
+
/** Job started processing */
|
|
227
|
+
active: (job: Job<T, R>) => void;
|
|
228
|
+
/** Job was added to the queue */
|
|
229
|
+
added: (job: Job<T, R>) => void;
|
|
230
|
+
/** Rate limit hit - job delayed */
|
|
231
|
+
rateLimited: (job: Job<T, R>) => void;
|
|
232
|
+
/** Job progress updated */
|
|
233
|
+
progress: (job: Job<T, R>, progress: number) => void;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Rate limiter configuration
|
|
237
|
+
*/
|
|
238
|
+
interface RateLimitOptions {
|
|
239
|
+
/** Maximum number of jobs to process per interval */
|
|
240
|
+
max: number;
|
|
241
|
+
/** Time window in ms (default: 1000 = 1 second) */
|
|
242
|
+
duration?: number;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Queue options
|
|
246
|
+
*/
|
|
247
|
+
interface QueueOptions {
|
|
248
|
+
/** Polling interval in ms when no jobs (default: 1000) */
|
|
249
|
+
pollInterval?: number;
|
|
250
|
+
/** Concurrency limit (default: 1) */
|
|
251
|
+
concurrency?: number;
|
|
252
|
+
/** Visibility timeout in ms - how long a job can be processing before considered stalled (default: 30000) */
|
|
253
|
+
visibilityTimeout?: number;
|
|
254
|
+
/** How often to check for stalled jobs in ms (default: 5000) */
|
|
255
|
+
stalledInterval?: number;
|
|
256
|
+
/** Rate limiting configuration */
|
|
257
|
+
rateLimit?: RateLimitOptions;
|
|
258
|
+
/** Custom logger (default: consoleLogger) */
|
|
259
|
+
logger?: Logger;
|
|
260
|
+
/** Maximum job payload size in bytes (default: unlimited) */
|
|
261
|
+
maxPayloadSize?: number;
|
|
262
|
+
/** Maximum queue size - rejects new jobs when exceeded (default: unlimited) */
|
|
263
|
+
maxQueueSize?: number;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Queue metrics snapshot
|
|
267
|
+
*/
|
|
268
|
+
interface QueueMetrics {
|
|
269
|
+
/** Number of jobs waiting to be processed */
|
|
270
|
+
waiting: number;
|
|
271
|
+
/** Number of jobs currently being processed */
|
|
272
|
+
active: number;
|
|
273
|
+
/** Number of failed jobs in DLQ */
|
|
274
|
+
failed: number;
|
|
275
|
+
/** Total jobs completed since start */
|
|
276
|
+
completed: number;
|
|
277
|
+
/** Total jobs that failed (moved to DLQ) since start */
|
|
278
|
+
totalFailed: number;
|
|
279
|
+
/** Total job processing time in ms */
|
|
280
|
+
totalProcessingTime: number;
|
|
281
|
+
/** Average job processing time in ms */
|
|
282
|
+
avgProcessingTime: number;
|
|
283
|
+
/** Jobs processed per second (recent) */
|
|
284
|
+
throughput: number;
|
|
285
|
+
}
|
|
286
|
+
type EventCallback = (...args: unknown[]) => void;
|
|
287
|
+
/**
|
|
288
|
+
* Events emitted by a JobHandle
|
|
289
|
+
*/
|
|
290
|
+
interface JobHandleEvents<
|
|
291
|
+
TData,
|
|
292
|
+
TResult
|
|
293
|
+
> {
|
|
294
|
+
completed: (job: Job<TData, TResult>, result: TResult | undefined) => void;
|
|
295
|
+
failed: (job: Job<TData, TResult>, error: Error) => void;
|
|
296
|
+
retry: (job: Job<TData, TResult>, error: Error) => void;
|
|
297
|
+
stalled: (job: Job<TData, TResult>) => void;
|
|
298
|
+
timeout: (job: Job<TData, TResult>) => void;
|
|
299
|
+
active: (job: Job<TData, TResult>) => void;
|
|
300
|
+
added: (job: Job<TData, TResult>) => void;
|
|
301
|
+
progress: (job: Job<TData, TResult>, progress: number) => void;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Options for defining a job type
|
|
305
|
+
*/
|
|
306
|
+
interface JobDefineOptions {
|
|
307
|
+
maxAttempts?: number;
|
|
308
|
+
timeout?: number;
|
|
309
|
+
backoff?: BackoffOptions;
|
|
310
|
+
priority?: number;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Options when adding a job instance (overrides defaults)
|
|
314
|
+
*/
|
|
315
|
+
interface JobAddOptions {
|
|
316
|
+
delay?: number;
|
|
317
|
+
priority?: number;
|
|
318
|
+
jobId?: string;
|
|
319
|
+
maxAttempts?: number;
|
|
320
|
+
timeout?: number;
|
|
321
|
+
backoff?: BackoffOptions;
|
|
322
|
+
repeat?: RepeatOptions;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Handler function for processing jobs
|
|
326
|
+
*/
|
|
327
|
+
type JobHandleHandler<
|
|
328
|
+
TData,
|
|
329
|
+
TResult
|
|
330
|
+
> = (data: TData, ctx: JobContext) => Promise<TResult | void> | TResult | void;
|
|
331
|
+
/**
|
|
332
|
+
* Interface for queue operations needed by JobHandle
|
|
333
|
+
*/
|
|
334
|
+
interface JobHandleQueue {
|
|
335
|
+
addJob(name: string, data: unknown, options: JobOptions): Promise<Job | null>;
|
|
336
|
+
addJobBulk(jobs: Array<{
|
|
337
|
+
name: string;
|
|
338
|
+
data: unknown;
|
|
339
|
+
options?: JobOptions;
|
|
340
|
+
}>): Promise<Job[]>;
|
|
341
|
+
processJob(name: string, handler: (job: Job, ctx: JobContext) => Promise<unknown>): void;
|
|
342
|
+
subscribeToEvent(event: string, name: string, callback: EventCallback): void;
|
|
343
|
+
unsubscribeFromEvent(event: string, name: string, callback: EventCallback): void;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* A typed handle for a specific job type.
|
|
347
|
+
* Provides type-safe methods for adding and processing jobs.
|
|
348
|
+
*/
|
|
349
|
+
declare class JobHandle<
|
|
350
|
+
TData = unknown,
|
|
351
|
+
TResult = void
|
|
352
|
+
> {
|
|
353
|
+
private readonly queue;
|
|
354
|
+
readonly name: string;
|
|
355
|
+
private readonly defaults;
|
|
356
|
+
private events;
|
|
357
|
+
private onceEvents;
|
|
358
|
+
private handler;
|
|
359
|
+
constructor(queue: JobHandleQueue, name: string, defaults?: JobDefineOptions);
|
|
360
|
+
/**
|
|
361
|
+
* Register a handler for this job type
|
|
362
|
+
*/
|
|
363
|
+
process(handler: JobHandleHandler<TData, TResult>): this;
|
|
364
|
+
/**
|
|
365
|
+
* Add a job to the queue
|
|
366
|
+
*/
|
|
367
|
+
add(data: TData, options?: JobAddOptions): Promise<Job<TData, TResult> | null>;
|
|
368
|
+
/**
|
|
369
|
+
* Add multiple jobs to the queue
|
|
370
|
+
*/
|
|
371
|
+
addBulk(items: Array<{
|
|
372
|
+
data: TData;
|
|
373
|
+
options?: JobAddOptions;
|
|
374
|
+
}>): Promise<Job<TData, TResult>[]>;
|
|
375
|
+
/**
|
|
376
|
+
* Subscribe to events for this job type
|
|
377
|
+
*/
|
|
378
|
+
on<K extends keyof JobHandleEvents<TData, TResult>>(event: K, callback: JobHandleEvents<TData, TResult>[K]): this;
|
|
379
|
+
/**
|
|
380
|
+
* Subscribe to a single occurrence of an event
|
|
381
|
+
*/
|
|
382
|
+
once<K extends keyof JobHandleEvents<TData, TResult>>(event: K, callback: JobHandleEvents<TData, TResult>[K]): this;
|
|
383
|
+
/**
|
|
384
|
+
* Unsubscribe from events
|
|
385
|
+
*/
|
|
386
|
+
off<K extends keyof JobHandleEvents<TData, TResult>>(event: K, callback: JobHandleEvents<TData, TResult>[K]): this;
|
|
387
|
+
}
|
|
388
|
+
type EventCallback2 = (...args: unknown[]) => void;
|
|
389
|
+
/**
|
|
390
|
+
* Type-safe job queue with pluggable backends
|
|
391
|
+
*/
|
|
392
|
+
declare class Queue implements JobHandleQueue {
|
|
393
|
+
private backend;
|
|
394
|
+
private handlers;
|
|
395
|
+
private events;
|
|
396
|
+
private onceEvents;
|
|
397
|
+
private jobEvents;
|
|
398
|
+
private running;
|
|
399
|
+
private processing;
|
|
400
|
+
private pollInterval;
|
|
401
|
+
private concurrency;
|
|
402
|
+
private visibilityTimeout;
|
|
403
|
+
private stalledInterval;
|
|
404
|
+
private pollTimer;
|
|
405
|
+
private stalledTimer;
|
|
406
|
+
private activeJobs;
|
|
407
|
+
private shuttingDown;
|
|
408
|
+
private shutdownResolve;
|
|
409
|
+
private rateLimit;
|
|
410
|
+
private rateLimitTokens;
|
|
411
|
+
private rateLimitLastRefill;
|
|
412
|
+
private logger;
|
|
413
|
+
private maxPayloadSize;
|
|
414
|
+
private maxQueueSize;
|
|
415
|
+
private metricsData;
|
|
416
|
+
constructor(backend: Backend, options?: QueueOptions);
|
|
417
|
+
/**
|
|
418
|
+
* Add a job to the queue (internal)
|
|
419
|
+
* @internal
|
|
420
|
+
*/
|
|
421
|
+
private add;
|
|
422
|
+
/**
|
|
423
|
+
* Add multiple jobs to the queue (internal)
|
|
424
|
+
* @internal
|
|
425
|
+
*/
|
|
426
|
+
private addBulk;
|
|
427
|
+
/**
|
|
428
|
+
* Define a new job type and return a typed handle for it.
|
|
429
|
+
* The handle provides type-safe methods for adding and processing jobs.
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
* const sendEmail = queue.define<{ to: string; subject: string }>("send-email", {
|
|
433
|
+
* maxAttempts: 5,
|
|
434
|
+
* timeout: 60_000,
|
|
435
|
+
* });
|
|
436
|
+
*
|
|
437
|
+
* sendEmail.process(async (data, ctx) => {
|
|
438
|
+
* await mail(data.to, data.subject);
|
|
439
|
+
* });
|
|
440
|
+
*
|
|
441
|
+
* await sendEmail.add({ to: "test@example.com", subject: "Hello" });
|
|
442
|
+
*/
|
|
443
|
+
define<
|
|
444
|
+
TData,
|
|
445
|
+
TResult = void
|
|
446
|
+
>(name: string, defaults?: JobDefineOptions): JobHandle<TData, TResult>;
|
|
447
|
+
/** @internal */
|
|
448
|
+
addJob(name: string, data: unknown, options: JobOptions): Promise<Job | null>;
|
|
449
|
+
/** @internal */
|
|
450
|
+
addJobBulk(jobs: Array<{
|
|
451
|
+
name: string;
|
|
452
|
+
data: unknown;
|
|
453
|
+
options?: JobOptions;
|
|
454
|
+
}>): Promise<Job[]>;
|
|
455
|
+
/** @internal */
|
|
456
|
+
processJob(name: string, handler: (job: Job, ctx: JobContext) => Promise<unknown>): void;
|
|
457
|
+
/** @internal */
|
|
458
|
+
subscribeToEvent(event: string, name: string, callback: EventCallback2): void;
|
|
459
|
+
/** @internal */
|
|
460
|
+
unsubscribeFromEvent(event: string, name: string, callback: EventCallback2): void;
|
|
461
|
+
/**
|
|
462
|
+
* Start processing jobs
|
|
463
|
+
*/
|
|
464
|
+
start(): void;
|
|
465
|
+
/**
|
|
466
|
+
* Stop processing jobs gracefully
|
|
467
|
+
* @param timeout Max time to wait for in-flight jobs (default: 30000ms)
|
|
468
|
+
* @returns Promise that resolves when all jobs complete or timeout
|
|
469
|
+
*/
|
|
470
|
+
stop(timeout?: number): Promise<void>;
|
|
471
|
+
/**
|
|
472
|
+
* Pause processing (finish current jobs but don't pick up new ones)
|
|
473
|
+
*/
|
|
474
|
+
pause(): void;
|
|
475
|
+
/**
|
|
476
|
+
* Resume processing after pause
|
|
477
|
+
*/
|
|
478
|
+
resume(): void;
|
|
479
|
+
/**
|
|
480
|
+
* Wait for all current jobs to complete
|
|
481
|
+
*/
|
|
482
|
+
drain(): Promise<void>;
|
|
483
|
+
/**
|
|
484
|
+
* Subscribe to queue events
|
|
485
|
+
*/
|
|
486
|
+
on<K extends keyof QueueEvents>(event: K, callback: QueueEvents[K]): this;
|
|
487
|
+
/**
|
|
488
|
+
* Subscribe to a single occurrence of an event
|
|
489
|
+
*/
|
|
490
|
+
once<K extends keyof QueueEvents>(event: K, callback: QueueEvents[K]): this;
|
|
491
|
+
/**
|
|
492
|
+
* Unsubscribe from queue events
|
|
493
|
+
*/
|
|
494
|
+
off<K extends keyof QueueEvents>(event: K, callback: QueueEvents[K]): this;
|
|
495
|
+
/**
|
|
496
|
+
* Get current queue size (waiting jobs)
|
|
497
|
+
*/
|
|
498
|
+
size(): Promise<number>;
|
|
499
|
+
/**
|
|
500
|
+
* Get count of active (processing) jobs
|
|
501
|
+
*/
|
|
502
|
+
activeCount(): Promise<number>;
|
|
503
|
+
/**
|
|
504
|
+
* Get count of failed jobs
|
|
505
|
+
*/
|
|
506
|
+
failedCount(): Promise<number>;
|
|
507
|
+
/**
|
|
508
|
+
* Get failed jobs
|
|
509
|
+
*/
|
|
510
|
+
getFailed(limit?: number): Promise<Array<{
|
|
511
|
+
job: Job;
|
|
512
|
+
error: string;
|
|
513
|
+
failedAt: number;
|
|
514
|
+
}>>;
|
|
515
|
+
/**
|
|
516
|
+
* Get a completed job with its result
|
|
517
|
+
*/
|
|
518
|
+
getCompleted(jobId: string): Promise<{
|
|
519
|
+
job: Job;
|
|
520
|
+
result: unknown;
|
|
521
|
+
completedAt: number;
|
|
522
|
+
} | null>;
|
|
523
|
+
/**
|
|
524
|
+
* Get count of completed jobs (with stored results)
|
|
525
|
+
*/
|
|
526
|
+
completedCount(): Promise<number>;
|
|
527
|
+
/**
|
|
528
|
+
* Get recent completed jobs with results
|
|
529
|
+
*/
|
|
530
|
+
getCompletedJobs(limit?: number): Promise<Array<{
|
|
531
|
+
job: Job;
|
|
532
|
+
result: unknown;
|
|
533
|
+
completedAt: number;
|
|
534
|
+
}>>;
|
|
535
|
+
/**
|
|
536
|
+
* Retry a failed job
|
|
537
|
+
*/
|
|
538
|
+
retryFailed(jobId: string): Promise<boolean>;
|
|
539
|
+
/**
|
|
540
|
+
* Remove a job by ID
|
|
541
|
+
*/
|
|
542
|
+
remove(jobId: string): Promise<boolean>;
|
|
543
|
+
/**
|
|
544
|
+
* Clear all jobs
|
|
545
|
+
*/
|
|
546
|
+
clear(): Promise<void>;
|
|
547
|
+
/**
|
|
548
|
+
* Close the queue and backend
|
|
549
|
+
*/
|
|
550
|
+
close(): Promise<void>;
|
|
551
|
+
/**
|
|
552
|
+
* Get queue metrics
|
|
553
|
+
*/
|
|
554
|
+
getMetrics(): Promise<QueueMetrics>;
|
|
555
|
+
private startStalledChecker;
|
|
556
|
+
private checkStalled;
|
|
557
|
+
private checkRateLimit;
|
|
558
|
+
private tick;
|
|
559
|
+
private executeJob;
|
|
560
|
+
private scheduleNextRepeat;
|
|
561
|
+
private emit;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* In-memory backend - single process, no persistence
|
|
565
|
+
* Good for development, testing, or simple use cases
|
|
566
|
+
* Uses a min-heap for O(log n) job retrieval by priority
|
|
567
|
+
*/
|
|
568
|
+
declare class MemoryBackend implements Backend {
|
|
569
|
+
/** Waiting jobs heap (sorted by priority, then scheduledAt) */
|
|
570
|
+
private waitingHeap;
|
|
571
|
+
/** Waiting jobs map for O(1) lookup by ID */
|
|
572
|
+
private waiting;
|
|
573
|
+
/** Active jobs being processed */
|
|
574
|
+
private active;
|
|
575
|
+
/** Failed jobs (dead letter queue) */
|
|
576
|
+
private failed;
|
|
577
|
+
/** Completed jobs with results */
|
|
578
|
+
private completed;
|
|
579
|
+
/** All job IDs for deduplication */
|
|
580
|
+
private allIds;
|
|
581
|
+
/** Job progress */
|
|
582
|
+
private progress;
|
|
583
|
+
private listener;
|
|
584
|
+
push(job: Job): Promise<boolean>;
|
|
585
|
+
pushBulk(jobs: Job[]): Promise<number>;
|
|
586
|
+
pop(visibilityTimeout: number): Promise<Job | null>;
|
|
587
|
+
ack(jobId: string, result?: unknown): Promise<void>;
|
|
588
|
+
nack(job: Job, nextAttemptAt: number): Promise<void>;
|
|
589
|
+
fail(job: Job, error: Error): Promise<void>;
|
|
590
|
+
getStalled(): Promise<Job[]>;
|
|
591
|
+
updateProgress(jobId: string, progress: number): Promise<void>;
|
|
592
|
+
getCompleted(jobId: string): Promise<{
|
|
593
|
+
job: Job;
|
|
594
|
+
result: unknown;
|
|
595
|
+
completedAt: number;
|
|
596
|
+
} | null>;
|
|
597
|
+
completedCount(): Promise<number>;
|
|
598
|
+
getCompletedJobs(limit?: number): Promise<Array<{
|
|
599
|
+
job: Job;
|
|
600
|
+
result: unknown;
|
|
601
|
+
completedAt: number;
|
|
602
|
+
}>>;
|
|
603
|
+
subscribe(callback: () => void): void;
|
|
604
|
+
unsubscribe(): void;
|
|
605
|
+
size(): Promise<number>;
|
|
606
|
+
activeCount(): Promise<number>;
|
|
607
|
+
failedCount(): Promise<number>;
|
|
608
|
+
getFailed(limit?: number): Promise<Array<{
|
|
609
|
+
job: Job;
|
|
610
|
+
error: string;
|
|
611
|
+
failedAt: number;
|
|
612
|
+
}>>;
|
|
613
|
+
retryFailed(jobId: string): Promise<boolean>;
|
|
614
|
+
remove(jobId: string): Promise<boolean>;
|
|
615
|
+
clear(): Promise<void>;
|
|
616
|
+
close(): Promise<void>;
|
|
617
|
+
private notify;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* BroadcastChannel backend - cross-tab/worker communication
|
|
621
|
+
*
|
|
622
|
+
* Uses BroadcastChannel API for real-time sync between:
|
|
623
|
+
* - Browser tabs (same origin)
|
|
624
|
+
* - Web Workers
|
|
625
|
+
* - Bun/Node worker threads
|
|
626
|
+
*
|
|
627
|
+
* Uses distributed claim protocol to prevent duplicate job processing.
|
|
628
|
+
*/
|
|
629
|
+
declare class BroadcastBackend implements Backend {
|
|
630
|
+
private waiting;
|
|
631
|
+
private active;
|
|
632
|
+
private failed;
|
|
633
|
+
private completed;
|
|
634
|
+
private allIds;
|
|
635
|
+
private progress;
|
|
636
|
+
private channel;
|
|
637
|
+
private listener;
|
|
638
|
+
private isLeader;
|
|
639
|
+
private leaderTimeout;
|
|
640
|
+
private instanceId;
|
|
641
|
+
private pendingClaims;
|
|
642
|
+
constructor(channelName?: string);
|
|
643
|
+
private electLeader;
|
|
644
|
+
private handleMessage;
|
|
645
|
+
push(job: Job): Promise<boolean>;
|
|
646
|
+
pushBulk(jobs: Job[]): Promise<number>;
|
|
647
|
+
pop(visibilityTimeout: number): Promise<Job | null>;
|
|
648
|
+
private tryClaim;
|
|
649
|
+
ack(jobId: string, result?: unknown): Promise<void>;
|
|
650
|
+
nack(job: Job, nextAttemptAt: number): Promise<void>;
|
|
651
|
+
fail(job: Job, error: Error): Promise<void>;
|
|
652
|
+
getStalled(): Promise<Job[]>;
|
|
653
|
+
updateProgress(jobId: string, progress: number): Promise<void>;
|
|
654
|
+
getCompleted(jobId: string): Promise<{
|
|
655
|
+
job: Job;
|
|
656
|
+
result: unknown;
|
|
657
|
+
completedAt: number;
|
|
658
|
+
} | null>;
|
|
659
|
+
completedCount(): Promise<number>;
|
|
660
|
+
getCompletedJobs(limit?: number): Promise<Array<{
|
|
661
|
+
job: Job;
|
|
662
|
+
result: unknown;
|
|
663
|
+
completedAt: number;
|
|
664
|
+
}>>;
|
|
665
|
+
subscribe(callback: () => void): void;
|
|
666
|
+
unsubscribe(): void;
|
|
667
|
+
size(): Promise<number>;
|
|
668
|
+
activeCount(): Promise<number>;
|
|
669
|
+
failedCount(): Promise<number>;
|
|
670
|
+
getFailed(limit?: number): Promise<Array<{
|
|
671
|
+
job: Job;
|
|
672
|
+
error: string;
|
|
673
|
+
failedAt: number;
|
|
674
|
+
}>>;
|
|
675
|
+
retryFailed(jobId: string): Promise<boolean>;
|
|
676
|
+
remove(jobId: string): Promise<boolean>;
|
|
677
|
+
clear(): Promise<void>;
|
|
678
|
+
close(): Promise<void>;
|
|
679
|
+
private notify;
|
|
680
|
+
}
|
|
681
|
+
type RedisClient = InstanceType<typeof Bun.RedisClient>;
|
|
682
|
+
/**
|
|
683
|
+
* Redis backend options
|
|
684
|
+
*/
|
|
685
|
+
interface RedisBackendOptions {
|
|
686
|
+
/** Key prefix for all queue data (default: "qwerk") */
|
|
687
|
+
prefix?: string;
|
|
688
|
+
/** Separate client for pub/sub subscriptions (optional, will create one if not provided) */
|
|
689
|
+
subscriber?: RedisClient;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Redis backend - distributed, persistent job queue
|
|
693
|
+
*
|
|
694
|
+
* Uses atomic Lua scripts for safe concurrent access.
|
|
695
|
+
* Requires Bun's built-in Redis client.
|
|
696
|
+
*/
|
|
697
|
+
declare class RedisBackend implements Backend {
|
|
698
|
+
private client;
|
|
699
|
+
private subscriber;
|
|
700
|
+
private prefix;
|
|
701
|
+
private listener;
|
|
702
|
+
private ownsSubscriber;
|
|
703
|
+
private url;
|
|
704
|
+
constructor(url: string, options?: RedisBackendOptions);
|
|
705
|
+
private key;
|
|
706
|
+
/**
|
|
707
|
+
* Execute a Lua script via EVAL command
|
|
708
|
+
*/
|
|
709
|
+
private evalScript;
|
|
710
|
+
push(job: Job): Promise<boolean>;
|
|
711
|
+
pushBulk(jobs: Job[]): Promise<number>;
|
|
712
|
+
pop(visibilityTimeout: number): Promise<Job | null>;
|
|
713
|
+
ack(jobId: string, result?: unknown): Promise<void>;
|
|
714
|
+
nack(job: Job, nextAttemptAt: number): Promise<void>;
|
|
715
|
+
fail(job: Job, error: Error): Promise<void>;
|
|
716
|
+
getStalled(): Promise<Job[]>;
|
|
717
|
+
updateProgress(jobId: string, progress: number): Promise<void>;
|
|
718
|
+
getCompleted(jobId: string): Promise<{
|
|
719
|
+
job: Job;
|
|
720
|
+
result: unknown;
|
|
721
|
+
completedAt: number;
|
|
722
|
+
} | null>;
|
|
723
|
+
completedCount(): Promise<number>;
|
|
724
|
+
getCompletedJobs(limit?: number): Promise<Array<{
|
|
725
|
+
job: Job;
|
|
726
|
+
result: unknown;
|
|
727
|
+
completedAt: number;
|
|
728
|
+
}>>;
|
|
729
|
+
subscribe(callback: () => void): void;
|
|
730
|
+
unsubscribe(): void;
|
|
731
|
+
size(): Promise<number>;
|
|
732
|
+
activeCount(): Promise<number>;
|
|
733
|
+
failedCount(): Promise<number>;
|
|
734
|
+
getFailed(limit?: number): Promise<Array<{
|
|
735
|
+
job: Job;
|
|
736
|
+
error: string;
|
|
737
|
+
failedAt: number;
|
|
738
|
+
}>>;
|
|
739
|
+
retryFailed(jobId: string): Promise<boolean>;
|
|
740
|
+
remove(jobId: string): Promise<boolean>;
|
|
741
|
+
clear(): Promise<void>;
|
|
742
|
+
close(): Promise<void>;
|
|
743
|
+
}
|
|
744
|
+
export { silentLogger, consoleLogger, RepeatOptions, RedisBackendOptions, RedisBackend, RateLimitOptions, QueueOptions, QueueMetrics, QueueEvents, Queue, MemoryBackend, Logger, JobStatus, JobOptions, JobHandleHandler, JobHandleEvents, JobHandle, JobDefineOptions, JobContext, JobAddOptions, Job, BroadcastBackend, BackoffOptions, Backend };
|