@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/build/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Q as QueueManagerConfig, W as WorkerCycle, A as Adapter, R as RetryConfig, d as JobFactory, e as Job, f as JobClass, b as ScheduleData, g as ScheduleStatus, c as ScheduleListOptions } from './index-2Ng_OpVK.js';
2
- export { h as ScheduleBuilder, i as customBackoff, j as exponentialBackoff, k as fixedBackoff, l as linearBackoff } from './index-2Ng_OpVK.js';
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 jobName(): string;
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-NPQKBCCY.js";
3
+ } from "./chunk-PBGPIFI5.js";
4
4
  import {
5
5
  Locator,
6
6
  QueueManager,
7
7
  debug_default
8
- } from "./chunk-US7THLSZ.js";
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
- #jobName;
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(jobName, payload) {
190
- this.#jobName = jobName;
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.#jobName,
279
- jobName: this.#jobName,
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
- /** Static options for this job class (queue, retries, timeout, etc.) */
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
- /** The payload data passed to this job instance */
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
- * Create a new job instance.
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 (provided by the worker)
578
+ * @param context - The job execution context
579
+ * @param signal - Optional abort signal for timeout handling
580
+ *
581
+ * @internal
364
582
  */
365
- constructor(payload, context) {
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 dispatcher = new JobDispatcher(
394
- this.jobName,
395
- payload
396
- );
397
- if (this.options.queue) {
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 (this.options.adapter) {
401
- dispatcher.with(this.options.adapter);
618
+ if (options.adapter) {
619
+ dispatcher.with(options.adapter);
402
620
  }
403
- if (this.options.priority !== void 0) {
404
- dispatcher.priority(this.options.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
- return new ScheduleBuilder(this.jobName, payload);
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 randomUUID2 } from "crypto";
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 = randomUUID2();
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 = Object.freeze({
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, job.payload, context) : new JobClass(job.payload, context);
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
- await this.#adapter.failJob(job.id, queue, error);
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(signal), abortPromise]);
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.jobName,
1148
+ schedule.name,
883
1149
  schedule.id,
884
1150
  schedule.runCount + 1
885
1151
  );
886
- const JobClass = Locator.get(schedule.jobName);
1152
+ const JobClass = Locator.get(schedule.name);
887
1153
  const queue = JobClass?.options?.queue ?? "default";
888
1154
  await this.#adapter.pushOn(queue, {
889
- id: randomUUID2(),
890
- name: schedule.jobName,
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 jobName() {
909
- return this.#data.jobName;
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.jobName, this.#data.payload);
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,