@boringnode/queue 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +230 -358
- package/build/{chunk-US7THLSZ.js → chunk-LI2ZMCNO.js} +17 -3
- package/build/chunk-LI2ZMCNO.js.map +1 -0
- package/build/{chunk-NPQKBCCY.js → chunk-PBGPIFI5.js} +15 -1
- package/build/chunk-PBGPIFI5.js.map +1 -0
- package/build/{index-2Ng_OpVK.d.ts → index-PDfE6h8d.d.ts} +454 -36
- package/build/index.d.ts +8 -4
- package/build/index.js +313 -46
- package/build/index.js.map +1 -1
- package/build/src/contracts/adapter.d.ts +1 -1
- package/build/src/drivers/knex_adapter.d.ts +6 -3
- package/build/src/drivers/knex_adapter.js +94 -12
- package/build/src/drivers/knex_adapter.js.map +1 -1
- package/build/src/drivers/redis_adapter.d.ts +6 -3
- package/build/src/drivers/redis_adapter.js +337 -96
- package/build/src/drivers/redis_adapter.js.map +1 -1
- package/build/src/drivers/sync_adapter.d.ts +6 -3
- package/build/src/drivers/sync_adapter.js +18 -6
- package/build/src/drivers/sync_adapter.js.map +1 -1
- package/build/src/types/index.d.ts +1 -1
- package/build/src/types/main.d.ts +1 -1
- package/package.json +3 -2
- package/build/chunk-NPQKBCCY.js.map +0 -1
- package/build/chunk-US7THLSZ.js.map +0 -1
package/build/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Q as QueueManagerConfig, W as WorkerCycle, A as Adapter, R as RetryConfig,
|
|
2
|
-
export {
|
|
1
|
+
import { Q as QueueManagerConfig, W as WorkerCycle, A as Adapter, R as RetryConfig, f as JobFactory, g as JobOptions, h as Job, i as JobClass, d as ScheduleData, j as ScheduleStatus, e as ScheduleListOptions } from './index-PDfE6h8d.js';
|
|
2
|
+
export { m as AdapterFactory, D as DispatchManyResult, l as JobBatchDispatcher, k as ScheduleBuilder, n as customBackoff, p as exponentialBackoff, q as fixedBackoff, o as linearBackoff } from './index-PDfE6h8d.js';
|
|
3
3
|
import * as _poppinss_utils from '@poppinss/utils';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -232,6 +232,10 @@ declare class QueueManagerSingleton {
|
|
|
232
232
|
* @returns The job factory function, or undefined if not configured
|
|
233
233
|
*/
|
|
234
234
|
getJobFactory(): JobFactory | undefined;
|
|
235
|
+
/**
|
|
236
|
+
* Get the merged job options for a job (priority: job > queue > global).
|
|
237
|
+
*/
|
|
238
|
+
getMergedJobOptions(queue: string, jobOptions?: JobOptions): JobOptions;
|
|
235
239
|
/**
|
|
236
240
|
* Clean up all adapter instances and reset state.
|
|
237
241
|
*
|
|
@@ -368,7 +372,7 @@ declare class Schedule {
|
|
|
368
372
|
#private;
|
|
369
373
|
constructor(data: ScheduleData);
|
|
370
374
|
get id(): string;
|
|
371
|
-
get
|
|
375
|
+
get name(): string;
|
|
372
376
|
get payload(): any;
|
|
373
377
|
get cronExpression(): string | null;
|
|
374
378
|
get everyMs(): number | null;
|
|
@@ -449,4 +453,4 @@ declare namespace exceptions {
|
|
|
449
453
|
export { exceptions_E_ADAPTER_INIT_ERROR as E_ADAPTER_INIT_ERROR, exceptions_E_CONFIGURATION_ERROR as E_CONFIGURATION_ERROR, exceptions_E_INVALID_BASE_DELAY as E_INVALID_BASE_DELAY, exceptions_E_INVALID_CRON_EXPRESSION as E_INVALID_CRON_EXPRESSION, exceptions_E_INVALID_DURATION_EXPRESSION as E_INVALID_DURATION_EXPRESSION, exceptions_E_INVALID_MAX_DELAY as E_INVALID_MAX_DELAY, exceptions_E_INVALID_MULTIPLIER as E_INVALID_MULTIPLIER, exceptions_E_INVALID_SCHEDULE_CONFIG as E_INVALID_SCHEDULE_CONFIG, exceptions_E_JOB_MAX_ATTEMPTS_REACHED as E_JOB_MAX_ATTEMPTS_REACHED, exceptions_E_JOB_NOT_FOUND as E_JOB_NOT_FOUND, exceptions_E_JOB_TIMEOUT as E_JOB_TIMEOUT, exceptions_E_NO_JOBS_FOUND as E_NO_JOBS_FOUND, exceptions_E_QUEUE_NOT_INITIALIZED as E_QUEUE_NOT_INITIALIZED };
|
|
450
454
|
}
|
|
451
455
|
|
|
452
|
-
export { Job, Locator, QueueManager, Schedule, Worker, exceptions as errors };
|
|
456
|
+
export { Job, JobFactory, Locator, QueueManager, Schedule, Worker, exceptions as errors };
|
package/build/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parse
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PBGPIFI5.js";
|
|
4
4
|
import {
|
|
5
5
|
Locator,
|
|
6
6
|
QueueManager,
|
|
7
7
|
debug_default
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LI2ZMCNO.js";
|
|
9
9
|
import {
|
|
10
10
|
DEFAULT_ERROR_RETRY_DELAY,
|
|
11
11
|
DEFAULT_IDLE_DELAY,
|
|
@@ -31,6 +31,7 @@ var JobDispatcher = class {
|
|
|
31
31
|
#adapter;
|
|
32
32
|
#delay;
|
|
33
33
|
#priority;
|
|
34
|
+
#groupId;
|
|
34
35
|
/**
|
|
35
36
|
* Create a new job dispatcher.
|
|
36
37
|
*
|
|
@@ -100,6 +101,28 @@ var JobDispatcher = class {
|
|
|
100
101
|
this.#priority = priority;
|
|
101
102
|
return this;
|
|
102
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Assign this job to a group.
|
|
106
|
+
*
|
|
107
|
+
* Jobs with the same groupId can be filtered and displayed together
|
|
108
|
+
* in monitoring UIs. Useful for batch operations like newsletters
|
|
109
|
+
* or bulk exports.
|
|
110
|
+
*
|
|
111
|
+
* @param groupId - Group identifier
|
|
112
|
+
* @returns This dispatcher for chaining
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* // Group newsletter jobs together
|
|
117
|
+
* await SendEmailJob.dispatch({ to: 'user@example.com' })
|
|
118
|
+
* .group('newsletter-jan-2025')
|
|
119
|
+
* .run()
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
group(groupId) {
|
|
123
|
+
this.#groupId = groupId;
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
103
126
|
/**
|
|
104
127
|
* Use a specific adapter for this job.
|
|
105
128
|
*
|
|
@@ -139,7 +162,8 @@ var JobDispatcher = class {
|
|
|
139
162
|
name: this.#name,
|
|
140
163
|
payload: this.#payload,
|
|
141
164
|
attempts: 0,
|
|
142
|
-
priority: this.#priority
|
|
165
|
+
priority: this.#priority,
|
|
166
|
+
groupId: this.#groupId
|
|
143
167
|
};
|
|
144
168
|
if (this.#delay) {
|
|
145
169
|
const parsedDelay = parse(this.#delay);
|
|
@@ -174,10 +198,148 @@ var JobDispatcher = class {
|
|
|
174
198
|
}
|
|
175
199
|
};
|
|
176
200
|
|
|
201
|
+
// src/job_batch_dispatcher.ts
|
|
202
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
203
|
+
var JobBatchDispatcher = class {
|
|
204
|
+
#name;
|
|
205
|
+
#payloads;
|
|
206
|
+
#queue = "default";
|
|
207
|
+
#adapter;
|
|
208
|
+
#priority;
|
|
209
|
+
#groupId;
|
|
210
|
+
/**
|
|
211
|
+
* Create a new batch job dispatcher.
|
|
212
|
+
*
|
|
213
|
+
* @param name - The job class name (used to locate the class at runtime)
|
|
214
|
+
* @param payloads - Array of data to pass to each job
|
|
215
|
+
*/
|
|
216
|
+
constructor(name, payloads) {
|
|
217
|
+
this.#name = name;
|
|
218
|
+
this.#payloads = payloads;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Set the target queue for all jobs.
|
|
222
|
+
*
|
|
223
|
+
* @param queue - Queue name (default: 'default')
|
|
224
|
+
* @returns This dispatcher for chaining
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```typescript
|
|
228
|
+
* await SendEmailJob.dispatchMany(payloads).toQueue('emails')
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
toQueue(queue) {
|
|
232
|
+
this.#queue = queue;
|
|
233
|
+
return this;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Set the priority for all jobs.
|
|
237
|
+
*
|
|
238
|
+
* Lower numbers = higher priority. Jobs with lower priority values
|
|
239
|
+
* are processed before jobs with higher values.
|
|
240
|
+
*
|
|
241
|
+
* @param priority - Priority level (1-10, default: 5)
|
|
242
|
+
* @returns This dispatcher for chaining
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```typescript
|
|
246
|
+
* await UrgentJob.dispatchMany(payloads).priority(1)
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
priority(priority) {
|
|
250
|
+
this.#priority = priority;
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Assign all jobs to a group.
|
|
255
|
+
*
|
|
256
|
+
* Jobs with the same groupId can be filtered and displayed together
|
|
257
|
+
* in monitoring UIs. Useful for batch operations like newsletters
|
|
258
|
+
* or bulk exports.
|
|
259
|
+
*
|
|
260
|
+
* @param groupId - Group identifier
|
|
261
|
+
* @returns This dispatcher for chaining
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* await SendEmailJob.dispatchMany(recipients)
|
|
266
|
+
* .group('newsletter-jan-2025')
|
|
267
|
+
* .run()
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
group(groupId) {
|
|
271
|
+
this.#groupId = groupId;
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Use a specific adapter for these jobs.
|
|
276
|
+
*
|
|
277
|
+
* @param adapter - Adapter name or factory function
|
|
278
|
+
* @returns This dispatcher for chaining
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```typescript
|
|
282
|
+
* await Job.dispatchMany(payloads).with('redis')
|
|
283
|
+
* ```
|
|
284
|
+
*/
|
|
285
|
+
with(adapter) {
|
|
286
|
+
this.#adapter = adapter;
|
|
287
|
+
return this;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Dispatch all jobs to the queue.
|
|
291
|
+
*
|
|
292
|
+
* @returns A DispatchManyResult containing all jobIds
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```typescript
|
|
296
|
+
* const { jobIds } = await SendEmailJob.dispatchMany(payloads).run()
|
|
297
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
async run() {
|
|
301
|
+
debug_default("dispatching %d jobs of type %s", this.#payloads.length, this.#name);
|
|
302
|
+
const adapter = this.#getAdapterInstance();
|
|
303
|
+
const jobs = this.#payloads.map((payload) => ({
|
|
304
|
+
id: randomUUID2(),
|
|
305
|
+
name: this.#name,
|
|
306
|
+
payload,
|
|
307
|
+
attempts: 0,
|
|
308
|
+
priority: this.#priority,
|
|
309
|
+
groupId: this.#groupId
|
|
310
|
+
}));
|
|
311
|
+
await adapter.pushManyOn(this.#queue, jobs);
|
|
312
|
+
return {
|
|
313
|
+
jobIds: jobs.map((job) => job.id)
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Thenable implementation for auto-dispatch when awaited.
|
|
318
|
+
*
|
|
319
|
+
* Allows `await Job.dispatchMany(payloads)` without explicit `.run()`.
|
|
320
|
+
*
|
|
321
|
+
* @param onFulfilled - Success callback
|
|
322
|
+
* @param onRejected - Error callback
|
|
323
|
+
* @returns Promise resolving to the DispatchManyResult
|
|
324
|
+
*/
|
|
325
|
+
then(onFulfilled, onRejected) {
|
|
326
|
+
return this.run().then(onFulfilled, onRejected);
|
|
327
|
+
}
|
|
328
|
+
#getAdapterInstance() {
|
|
329
|
+
if (!this.#adapter) {
|
|
330
|
+
return QueueManager.use();
|
|
331
|
+
}
|
|
332
|
+
if (typeof this.#adapter === "string") {
|
|
333
|
+
return QueueManager.use(this.#adapter);
|
|
334
|
+
}
|
|
335
|
+
return this.#adapter();
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
|
|
177
339
|
// src/schedule_builder.ts
|
|
178
340
|
import { CronExpressionParser } from "cron-parser";
|
|
179
341
|
var ScheduleBuilder = class {
|
|
180
|
-
#
|
|
342
|
+
#name;
|
|
181
343
|
#payload;
|
|
182
344
|
#id;
|
|
183
345
|
#cronExpression;
|
|
@@ -186,8 +348,8 @@ var ScheduleBuilder = class {
|
|
|
186
348
|
#from;
|
|
187
349
|
#to;
|
|
188
350
|
#limit;
|
|
189
|
-
constructor(
|
|
190
|
-
this.#
|
|
351
|
+
constructor(name, payload) {
|
|
352
|
+
this.#name = name;
|
|
191
353
|
this.#payload = payload;
|
|
192
354
|
}
|
|
193
355
|
/**
|
|
@@ -275,8 +437,8 @@ var ScheduleBuilder = class {
|
|
|
275
437
|
}
|
|
276
438
|
}
|
|
277
439
|
const config = {
|
|
278
|
-
id: this.#id ?? this.#
|
|
279
|
-
|
|
440
|
+
id: this.#id ?? this.#name,
|
|
441
|
+
name: this.#name,
|
|
280
442
|
payload: this.#payload,
|
|
281
443
|
cronExpression: this.#cronExpression,
|
|
282
444
|
everyMs: this.#everyMs,
|
|
@@ -331,9 +493,39 @@ var ScheduleBuilder = class {
|
|
|
331
493
|
var Job = class {
|
|
332
494
|
#payload;
|
|
333
495
|
#context;
|
|
334
|
-
|
|
496
|
+
#signal;
|
|
497
|
+
/**
|
|
498
|
+
* Static options for this job class.
|
|
499
|
+
*
|
|
500
|
+
* Override this property in subclasses to configure job behavior
|
|
501
|
+
* such as queue name, retry policy, timeout, and more.
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* ```typescript
|
|
505
|
+
* class SendEmailJob extends Job<SendEmailPayload> {
|
|
506
|
+
* static options = {
|
|
507
|
+
* queue: 'emails',
|
|
508
|
+
* maxRetries: 3,
|
|
509
|
+
* timeout: '30s',
|
|
510
|
+
* }
|
|
511
|
+
* }
|
|
512
|
+
* ```
|
|
513
|
+
*/
|
|
335
514
|
static options = {};
|
|
336
|
-
/**
|
|
515
|
+
/**
|
|
516
|
+
* The payload data passed to this job instance.
|
|
517
|
+
*
|
|
518
|
+
* Contains the data provided when the job was dispatched.
|
|
519
|
+
* Available after the job has been hydrated by the worker.
|
|
520
|
+
*
|
|
521
|
+
* @example
|
|
522
|
+
* ```typescript
|
|
523
|
+
* async execute() {
|
|
524
|
+
* const { to, subject, body } = this.payload
|
|
525
|
+
* await sendEmail(to, subject, body)
|
|
526
|
+
* }
|
|
527
|
+
* ```
|
|
528
|
+
*/
|
|
337
529
|
get payload() {
|
|
338
530
|
return this.#payload;
|
|
339
531
|
}
|
|
@@ -357,14 +549,41 @@ var Job = class {
|
|
|
357
549
|
return this.#context;
|
|
358
550
|
}
|
|
359
551
|
/**
|
|
360
|
-
*
|
|
552
|
+
* The abort signal for timeout handling.
|
|
553
|
+
*
|
|
554
|
+
* Check `signal.aborted` in long-running operations to handle timeouts gracefully.
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```typescript
|
|
558
|
+
* async execute() {
|
|
559
|
+
* for (const item of this.payload.items) {
|
|
560
|
+
* if (this.signal?.aborted) {
|
|
561
|
+
* throw new Error('Job timed out')
|
|
562
|
+
* }
|
|
563
|
+
* await processItem(item)
|
|
564
|
+
* }
|
|
565
|
+
* }
|
|
566
|
+
* ```
|
|
567
|
+
*/
|
|
568
|
+
get signal() {
|
|
569
|
+
return this.#signal;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Hydrate the job with payload, context, and optional abort signal.
|
|
573
|
+
*
|
|
574
|
+
* This method is called by the worker after instantiation to provide
|
|
575
|
+
* the job's runtime data. It should not be called directly by user code.
|
|
361
576
|
*
|
|
362
577
|
* @param payload - The data to be processed by this job
|
|
363
|
-
* @param context - The job execution context
|
|
578
|
+
* @param context - The job execution context
|
|
579
|
+
* @param signal - Optional abort signal for timeout handling
|
|
580
|
+
*
|
|
581
|
+
* @internal
|
|
364
582
|
*/
|
|
365
|
-
|
|
583
|
+
$hydrate(payload, context, signal) {
|
|
366
584
|
this.#payload = payload;
|
|
367
585
|
this.#context = Object.freeze(context);
|
|
586
|
+
this.#signal = signal;
|
|
368
587
|
}
|
|
369
588
|
/**
|
|
370
589
|
* Dispatch this job to the queue.
|
|
@@ -390,18 +609,59 @@ var Job = class {
|
|
|
390
609
|
* ```
|
|
391
610
|
*/
|
|
392
611
|
static dispatch(payload) {
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
)
|
|
397
|
-
|
|
398
|
-
dispatcher.toQueue(this.options.queue);
|
|
612
|
+
const options = this.options || {};
|
|
613
|
+
const jobName = options.name || this.name;
|
|
614
|
+
const dispatcher = new JobDispatcher(jobName, payload);
|
|
615
|
+
if (options.queue) {
|
|
616
|
+
dispatcher.toQueue(options.queue);
|
|
399
617
|
}
|
|
400
|
-
if (
|
|
401
|
-
dispatcher.with(
|
|
618
|
+
if (options.adapter) {
|
|
619
|
+
dispatcher.with(options.adapter);
|
|
402
620
|
}
|
|
403
|
-
if (
|
|
404
|
-
dispatcher.priority(
|
|
621
|
+
if (options.priority !== void 0) {
|
|
622
|
+
dispatcher.priority(options.priority);
|
|
623
|
+
}
|
|
624
|
+
return dispatcher;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Dispatch multiple jobs to the queue in a single batch.
|
|
628
|
+
*
|
|
629
|
+
* Returns a JobBatchDispatcher for fluent configuration before dispatching.
|
|
630
|
+
* The jobs are not actually dispatched until `.run()` is called or the
|
|
631
|
+
* dispatcher is awaited.
|
|
632
|
+
*
|
|
633
|
+
* This is more efficient than calling `dispatch()` multiple times as it
|
|
634
|
+
* uses batched operations (e.g., Redis pipeline, SQL batch insert).
|
|
635
|
+
*
|
|
636
|
+
* @param payloads - Array of data to pass to each job
|
|
637
|
+
* @returns A JobBatchDispatcher for fluent configuration
|
|
638
|
+
*
|
|
639
|
+
* @example
|
|
640
|
+
* ```typescript
|
|
641
|
+
* // Batch dispatch for newsletter
|
|
642
|
+
* const { jobIds } = await SendEmailJob.dispatchMany([
|
|
643
|
+
* { to: 'user1@example.com', subject: 'Newsletter' },
|
|
644
|
+
* { to: 'user2@example.com', subject: 'Newsletter' },
|
|
645
|
+
* ])
|
|
646
|
+
* .group('newsletter-jan-2025')
|
|
647
|
+
* .toQueue('emails')
|
|
648
|
+
* .run()
|
|
649
|
+
*
|
|
650
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
651
|
+
* ```
|
|
652
|
+
*/
|
|
653
|
+
static dispatchMany(payloads) {
|
|
654
|
+
const options = this.options || {};
|
|
655
|
+
const jobName = options.name || this.name;
|
|
656
|
+
const dispatcher = new JobBatchDispatcher(jobName, payloads);
|
|
657
|
+
if (options.queue) {
|
|
658
|
+
dispatcher.toQueue(options.queue);
|
|
659
|
+
}
|
|
660
|
+
if (options.adapter) {
|
|
661
|
+
dispatcher.with(options.adapter);
|
|
662
|
+
}
|
|
663
|
+
if (options.priority !== void 0) {
|
|
664
|
+
dispatcher.priority(options.priority);
|
|
405
665
|
}
|
|
406
666
|
return dispatcher;
|
|
407
667
|
}
|
|
@@ -431,12 +691,14 @@ var Job = class {
|
|
|
431
691
|
* ```
|
|
432
692
|
*/
|
|
433
693
|
static schedule(payload) {
|
|
434
|
-
|
|
694
|
+
const options = this.options || {};
|
|
695
|
+
const jobName = options.name || this.name;
|
|
696
|
+
return new ScheduleBuilder(jobName, payload);
|
|
435
697
|
}
|
|
436
698
|
};
|
|
437
699
|
|
|
438
700
|
// src/worker.ts
|
|
439
|
-
import { randomUUID as
|
|
701
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
440
702
|
import { setTimeout } from "timers/promises";
|
|
441
703
|
|
|
442
704
|
// src/job_pool.ts
|
|
@@ -542,7 +804,7 @@ var Worker = class {
|
|
|
542
804
|
*/
|
|
543
805
|
constructor(config) {
|
|
544
806
|
this.#config = config;
|
|
545
|
-
this.#id =
|
|
807
|
+
this.#id = randomUUID3();
|
|
546
808
|
this.#idleDelay = parse(config.worker?.idleDelay ?? DEFAULT_IDLE_DELAY);
|
|
547
809
|
this.#stalledInterval = parse(config.worker?.stalledInterval ?? DEFAULT_STALLED_INTERVAL);
|
|
548
810
|
this.#stalledThreshold = parse(config.worker?.stalledThreshold ?? DEFAULT_STALLED_THRESHOLD);
|
|
@@ -728,24 +990,25 @@ var Worker = class {
|
|
|
728
990
|
async #execute(job, queue) {
|
|
729
991
|
const startTime = performance.now();
|
|
730
992
|
debug_default("worker %s: executing job %s (%s)", this.#id, job.id, job.name);
|
|
731
|
-
const { instance, options, timeout } = await this.#initJob(job, queue);
|
|
993
|
+
const { instance, options, timeout, context, payload } = await this.#initJob(job, queue);
|
|
994
|
+
const retention = QueueManager.getMergedJobOptions(queue, options);
|
|
732
995
|
try {
|
|
733
|
-
await this.#executeWithTimeout(instance, timeout);
|
|
734
|
-
await this.#adapter.completeJob(job.id, queue);
|
|
996
|
+
await this.#executeWithTimeout(instance, payload, context, timeout);
|
|
997
|
+
await this.#adapter.completeJob(job.id, queue, retention.removeOnComplete);
|
|
735
998
|
const duration = (performance.now() - startTime).toFixed(2);
|
|
736
999
|
debug_default("worker %s: successfully executed job %s in %dms", this.#id, job.id, duration);
|
|
737
1000
|
} catch (e) {
|
|
738
1001
|
const isTimeout = e instanceof E_JOB_TIMEOUT;
|
|
739
1002
|
if (isTimeout && options.failOnTimeout) {
|
|
740
1003
|
debug_default("worker %s: job %s timed out and failOnTimeout is set", this.#id, job.id);
|
|
741
|
-
await this.#adapter.failJob(job.id, queue, e);
|
|
1004
|
+
await this.#adapter.failJob(job.id, queue, e, retention.removeOnFail);
|
|
742
1005
|
await instance.failed?.(e);
|
|
743
1006
|
return;
|
|
744
1007
|
}
|
|
745
1008
|
const mergedConfig = QueueManager.getMergedRetryConfig(queue, options.retry);
|
|
746
1009
|
if (typeof mergedConfig.maxRetries === "undefined" || mergedConfig.maxRetries <= 0) {
|
|
747
1010
|
debug_default("worker %s: job %s has no retries configured, marking as failed", this.#id, job.id);
|
|
748
|
-
await this.#adapter.failJob(job.id, queue, e);
|
|
1011
|
+
await this.#adapter.failJob(job.id, queue, e, retention.removeOnFail);
|
|
749
1012
|
await instance.failed?.(e);
|
|
750
1013
|
return;
|
|
751
1014
|
}
|
|
@@ -756,7 +1019,7 @@ var Worker = class {
|
|
|
756
1019
|
job.id,
|
|
757
1020
|
mergedConfig.maxRetries
|
|
758
1021
|
);
|
|
759
|
-
await this.#adapter.failJob(job.id, queue, e);
|
|
1022
|
+
await this.#adapter.failJob(job.id, queue, e, retention.removeOnFail);
|
|
760
1023
|
const exception = new E_JOB_MAX_ATTEMPTS_REACHED([job.name]);
|
|
761
1024
|
await instance.failed?.(exception);
|
|
762
1025
|
return;
|
|
@@ -774,7 +1037,7 @@ var Worker = class {
|
|
|
774
1037
|
async #initJob(job, queue) {
|
|
775
1038
|
try {
|
|
776
1039
|
const JobClass = Locator.getOrThrow(job.name);
|
|
777
|
-
const context =
|
|
1040
|
+
const context = {
|
|
778
1041
|
jobId: job.id,
|
|
779
1042
|
name: job.name,
|
|
780
1043
|
attempt: job.attempts + 1,
|
|
@@ -782,15 +1045,16 @@ var Worker = class {
|
|
|
782
1045
|
priority: job.priority ?? DEFAULT_PRIORITY,
|
|
783
1046
|
acquiredAt: new Date(job.acquiredAt),
|
|
784
1047
|
stalledCount: job.stalledCount ?? 0
|
|
785
|
-
}
|
|
1048
|
+
};
|
|
786
1049
|
const jobFactory = QueueManager.getJobFactory();
|
|
787
|
-
const instance = jobFactory ? await jobFactory(JobClass
|
|
1050
|
+
const instance = jobFactory ? await jobFactory(JobClass) : new JobClass();
|
|
788
1051
|
const options = JobClass.options || {};
|
|
789
1052
|
const timeout = this.#getJobTimeout(options);
|
|
790
|
-
return { instance, options, timeout };
|
|
1053
|
+
return { instance, options, timeout, context, payload: job.payload };
|
|
791
1054
|
} catch (error) {
|
|
792
1055
|
debug_default("worker %s: failed to initialize job %s (%s)", this.#id, job.id, job.name);
|
|
793
|
-
|
|
1056
|
+
const retention = QueueManager.getMergedJobOptions(queue);
|
|
1057
|
+
await this.#adapter.failJob(job.id, queue, error, retention.removeOnFail);
|
|
794
1058
|
throw error;
|
|
795
1059
|
}
|
|
796
1060
|
}
|
|
@@ -803,17 +1067,19 @@ var Worker = class {
|
|
|
803
1067
|
}
|
|
804
1068
|
return void 0;
|
|
805
1069
|
}
|
|
806
|
-
async #executeWithTimeout(instance, timeout) {
|
|
1070
|
+
async #executeWithTimeout(instance, payload, context, timeout) {
|
|
807
1071
|
if (!timeout) {
|
|
1072
|
+
instance.$hydrate(payload, context);
|
|
808
1073
|
return instance.execute();
|
|
809
1074
|
}
|
|
810
1075
|
const signal = AbortSignal.timeout(timeout);
|
|
1076
|
+
instance.$hydrate(payload, context, signal);
|
|
811
1077
|
const abortPromise = new Promise((_, reject) => {
|
|
812
1078
|
signal.addEventListener("abort", () => {
|
|
813
1079
|
reject(new E_JOB_TIMEOUT([instance.constructor.name, timeout]));
|
|
814
1080
|
});
|
|
815
1081
|
});
|
|
816
|
-
await Promise.race([instance.execute(
|
|
1082
|
+
await Promise.race([instance.execute(), abortPromise]);
|
|
817
1083
|
}
|
|
818
1084
|
async #acquireNextJob(queues) {
|
|
819
1085
|
for (const queue of queues) {
|
|
@@ -879,15 +1145,15 @@ var Worker = class {
|
|
|
879
1145
|
debug_default(
|
|
880
1146
|
"worker %s: dispatching scheduled job %s (schedule: %s, runCount: %d)",
|
|
881
1147
|
this.#id,
|
|
882
|
-
schedule.
|
|
1148
|
+
schedule.name,
|
|
883
1149
|
schedule.id,
|
|
884
1150
|
schedule.runCount + 1
|
|
885
1151
|
);
|
|
886
|
-
const JobClass = Locator.get(schedule.
|
|
1152
|
+
const JobClass = Locator.get(schedule.name);
|
|
887
1153
|
const queue = JobClass?.options?.queue ?? "default";
|
|
888
1154
|
await this.#adapter.pushOn(queue, {
|
|
889
|
-
id:
|
|
890
|
-
name: schedule.
|
|
1155
|
+
id: randomUUID3(),
|
|
1156
|
+
name: schedule.name,
|
|
891
1157
|
payload: schedule.payload,
|
|
892
1158
|
attempts: 0,
|
|
893
1159
|
priority: JobClass?.options?.priority
|
|
@@ -905,8 +1171,8 @@ var Schedule = class _Schedule {
|
|
|
905
1171
|
get id() {
|
|
906
1172
|
return this.#data.id;
|
|
907
1173
|
}
|
|
908
|
-
get
|
|
909
|
-
return this.#data.
|
|
1174
|
+
get name() {
|
|
1175
|
+
return this.#data.name;
|
|
910
1176
|
}
|
|
911
1177
|
get payload() {
|
|
912
1178
|
return this.#data.payload;
|
|
@@ -1003,7 +1269,7 @@ var Schedule = class _Schedule {
|
|
|
1003
1269
|
return;
|
|
1004
1270
|
}
|
|
1005
1271
|
const adapter = QueueManager.use();
|
|
1006
|
-
const dispatcher = new JobDispatcher(this.#data.
|
|
1272
|
+
const dispatcher = new JobDispatcher(this.#data.name, this.#data.payload);
|
|
1007
1273
|
await dispatcher.run();
|
|
1008
1274
|
const now = /* @__PURE__ */ new Date();
|
|
1009
1275
|
const newRunCount = this.#data.runCount + 1;
|
|
@@ -1163,6 +1429,7 @@ function customBackoff(config) {
|
|
|
1163
1429
|
}
|
|
1164
1430
|
export {
|
|
1165
1431
|
Job,
|
|
1432
|
+
JobBatchDispatcher,
|
|
1166
1433
|
Locator,
|
|
1167
1434
|
QueueManager,
|
|
1168
1435
|
Schedule,
|