power-queues 2.1.3 → 2.1.5

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/dist/index.cjs CHANGED
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  module.exports = __toCommonJS(index_exports);
26
26
 
27
27
  // src/PowerQueues.ts
28
+ var import_node_events = require("events");
28
29
  var import_power_redis = require("power-redis");
29
30
  var import_full_utils = require("full-utils");
30
31
  var import_uuid = require("uuid");
@@ -275,7 +276,7 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
275
276
  this.selectStuckTimeout = 6e4;
276
277
  this.selectStuckMaxTimeout = 80;
277
278
  this.selectCount = 200;
278
- this.selectTimeout = 5e3;
279
+ this.selectTimeout = 3e3;
279
280
  this.buildBatchCount = 800;
280
281
  this.buildBatchMaxCount = 1e4;
281
282
  this.retryCount = 1;
@@ -283,7 +284,7 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
283
284
  this.idemLockTimeout = 18e4;
284
285
  this.idemDoneTimeout = 6e4;
285
286
  this.logStatus = false;
286
- this.logStatusTimeout = 6e5;
287
+ this.logStatusTimeout = 18e5;
287
288
  this.approveCount = 2e3;
288
289
  this.removeOnExecuted = true;
289
290
  }
@@ -294,6 +295,7 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
294
295
  return this.host + ":" + process.pid;
295
296
  }
296
297
  async runQueue(queueName, from = "0-0") {
298
+ (0, import_node_events.setMaxListeners)(0, this.abort.signal);
297
299
  await this.createGroup(queueName, from);
298
300
  await this.consumerLoop(queueName, from);
299
301
  }
@@ -339,17 +341,26 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
339
341
  if (!filtered[key]) {
340
342
  filtered[key] = [];
341
343
  }
342
- filtered[key].push(tasks[index]);
344
+ filtered[key].push(tasks[index][1]);
343
345
  });
344
346
  for (let key in filtered) {
345
347
  const filteredTasks = filtered[key];
346
348
  const keySplit = key.split(":");
347
349
  const attempt = Number(keySplit[0]);
348
- await this.addTasks(queueName + (attempt >= this.retryCount - 1 ? ":dlq" : ""), filteredTasks.map((task) => ({ ...task[1] })), {
349
- createdAt: Number(keySplit[1]),
350
- job: keySplit[2],
351
- attempt: attempt + 1
352
- });
350
+ const job = String(keySplit[2]);
351
+ if (!(attempt >= this.retryCount - 1)) {
352
+ await this.addTasks(queueName, filteredTasks, {
353
+ job,
354
+ attempt: attempt + 1
355
+ });
356
+ } else if (this.logStatus) {
357
+ const statusKey = `${queueName}:${job}:`;
358
+ await this.setOne(statusKey + "err", Number(await this.getOne(statusKey + "err") || 0) + filteredTasks.length, this.logStatusTimeout);
359
+ await this.setOne(statusKey + "ready", Number(await this.getOne(statusKey + "ready") || 0) + filteredTasks.length, this.logStatusTimeout);
360
+ await this.addTasks(queueName + ":dlq", filteredTasks, {
361
+ job
362
+ });
363
+ }
353
364
  }
354
365
  } catch (err2) {
355
366
  throw new Error(`Batch error. ${err2.message}`);
@@ -469,8 +480,9 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
469
480
  }
470
481
  }
471
482
  }
483
+ let start = Date.now();
472
484
  if (!this.executeSync && promises.length > 0) {
473
- await Promise.all(promises.map((item) => item));
485
+ await Promise.all(promises.map((item) => item()));
474
486
  }
475
487
  await this.onBatchReady(queueName, result);
476
488
  if (!(0, import_full_utils.isArrFilled)(result) && contended > tasks.length >> 1) {
@@ -549,26 +561,24 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
549
561
  return await this.onSuccess(queueName, task);
550
562
  }
551
563
  async error(err, queueName, task) {
552
- const dlqKey = queueName + ":dlq";
553
564
  const taskP = { ...task };
554
- if (taskP.attempt >= this.retryCount - 1) {
555
- const statusKey = `${queueName}:${taskP.job}:`;
556
- if (this.logStatus) {
557
- await this.incr(statusKey + "err", this.logStatusTimeout);
558
- await this.incr(statusKey + "ready", this.logStatusTimeout);
559
- }
560
- await this.addTasks(dlqKey, [{ ...taskP.payload }], {
561
- createdAt: taskP.createdAt,
562
- job: taskP.job,
563
- attempt: taskP.attempt
564
- });
565
- } else {
565
+ if (!(taskP.attempt >= this.retryCount - 1)) {
566
566
  await this.onRetry(err, queueName, taskP);
567
567
  await this.addTasks(queueName, [{ ...taskP.payload }], {
568
568
  createdAt: taskP.createdAt,
569
569
  job: taskP.job,
570
570
  attempt: (taskP.attempt || 0) + 1
571
571
  });
572
+ } else if (this.logStatus) {
573
+ const dlqKey = queueName + ":dlq";
574
+ const statusKey = `${queueName}:${taskP.job}:`;
575
+ await this.incr(statusKey + "err", this.logStatusTimeout);
576
+ await this.incr(statusKey + "ready", this.logStatusTimeout);
577
+ await this.addTasks(dlqKey, [{ ...taskP.payload }], {
578
+ createdAt: taskP.createdAt,
579
+ job: taskP.job,
580
+ attempt: taskP.attempt
581
+ });
572
582
  }
573
583
  return await this.onError(err, queueName, { ...taskP, attempt: (taskP.attempt || 0) + 1 });
574
584
  }
@@ -616,22 +626,21 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
616
626
  return;
617
627
  }
618
628
  const workerHeartbeatTimeoutMs = Math.max(1e3, Math.floor(Math.max(5e3, this.idemLockTimeout | 0) / 4));
619
- let timer;
620
- let alive = true;
621
- let hbFails = 0;
629
+ let timer, alive = true, hbFails = 0;
622
630
  const stop = () => {
623
631
  alive = false;
624
632
  if (timer) {
625
633
  clearTimeout(timer);
626
634
  }
627
635
  };
628
- const signal = this.signal();
629
- const onAbort = () => stop();
630
- signal?.addEventListener?.("abort", onAbort, { once: true });
631
636
  const tick = async () => {
632
637
  if (!alive) {
633
638
  return;
634
639
  }
640
+ if (this.signal()?.aborted) {
641
+ stop();
642
+ return;
643
+ }
635
644
  try {
636
645
  const ok = await this.sendHeartbeat(keys);
637
646
  hbFails = ok ? 0 : hbFails + 1;
@@ -650,10 +659,7 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
650
659
  };
651
660
  timer = setTimeout(tick, workerHeartbeatTimeoutMs);
652
661
  timer.unref?.();
653
- return () => {
654
- signal?.removeEventListener?.("abort", onAbort);
655
- stop();
656
- };
662
+ return () => stop();
657
663
  }
658
664
  async runScript(name, keys, args, defaultCode) {
659
665
  if (!this.scripts[name]) {
package/dist/index.d.cts CHANGED
@@ -83,7 +83,7 @@ declare class PowerQueues extends PowerRedis {
83
83
  private payloadBatch;
84
84
  beforeExecute(queueName: string, tasks: Array<[string, any, number, string, string, number]>): Promise<[string, any, number, string, string, number][]>;
85
85
  onExecute(queueName: string, task: Task): Promise<Task>;
86
- onBatchReady(queueName: string, tasks: Array<Task>): Promise<void>;
86
+ onBatchReady(queueName: string, tasks: Task[]): Promise<void>;
87
87
  onSuccess(queueName: string, task: Task): Promise<Task>;
88
88
  onError(err: any, queueName: string, task: Task): Promise<Task>;
89
89
  onBatchError(err: any, queueName: string, tasks: Array<[string, any, number, string, string, number]>): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -83,7 +83,7 @@ declare class PowerQueues extends PowerRedis {
83
83
  private payloadBatch;
84
84
  beforeExecute(queueName: string, tasks: Array<[string, any, number, string, string, number]>): Promise<[string, any, number, string, string, number][]>;
85
85
  onExecute(queueName: string, task: Task): Promise<Task>;
86
- onBatchReady(queueName: string, tasks: Array<Task>): Promise<void>;
86
+ onBatchReady(queueName: string, tasks: Task[]): Promise<void>;
87
87
  onSuccess(queueName: string, task: Task): Promise<Task>;
88
88
  onError(err: any, queueName: string, task: Task): Promise<Task>;
89
89
  onBatchError(err: any, queueName: string, tasks: Array<[string, any, number, string, string, number]>): Promise<void>;
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/PowerQueues.ts
2
+ import { setMaxListeners } from "events";
2
3
  import { PowerRedis } from "power-redis";
3
4
  import {
4
5
  isObjFilled,
@@ -258,7 +259,7 @@ var PowerQueues = class extends PowerRedis {
258
259
  this.selectStuckTimeout = 6e4;
259
260
  this.selectStuckMaxTimeout = 80;
260
261
  this.selectCount = 200;
261
- this.selectTimeout = 5e3;
262
+ this.selectTimeout = 3e3;
262
263
  this.buildBatchCount = 800;
263
264
  this.buildBatchMaxCount = 1e4;
264
265
  this.retryCount = 1;
@@ -266,7 +267,7 @@ var PowerQueues = class extends PowerRedis {
266
267
  this.idemLockTimeout = 18e4;
267
268
  this.idemDoneTimeout = 6e4;
268
269
  this.logStatus = false;
269
- this.logStatusTimeout = 6e5;
270
+ this.logStatusTimeout = 18e5;
270
271
  this.approveCount = 2e3;
271
272
  this.removeOnExecuted = true;
272
273
  }
@@ -277,6 +278,7 @@ var PowerQueues = class extends PowerRedis {
277
278
  return this.host + ":" + process.pid;
278
279
  }
279
280
  async runQueue(queueName, from = "0-0") {
281
+ setMaxListeners(0, this.abort.signal);
280
282
  await this.createGroup(queueName, from);
281
283
  await this.consumerLoop(queueName, from);
282
284
  }
@@ -322,17 +324,26 @@ var PowerQueues = class extends PowerRedis {
322
324
  if (!filtered[key]) {
323
325
  filtered[key] = [];
324
326
  }
325
- filtered[key].push(tasks[index]);
327
+ filtered[key].push(tasks[index][1]);
326
328
  });
327
329
  for (let key in filtered) {
328
330
  const filteredTasks = filtered[key];
329
331
  const keySplit = key.split(":");
330
332
  const attempt = Number(keySplit[0]);
331
- await this.addTasks(queueName + (attempt >= this.retryCount - 1 ? ":dlq" : ""), filteredTasks.map((task) => ({ ...task[1] })), {
332
- createdAt: Number(keySplit[1]),
333
- job: keySplit[2],
334
- attempt: attempt + 1
335
- });
333
+ const job = String(keySplit[2]);
334
+ if (!(attempt >= this.retryCount - 1)) {
335
+ await this.addTasks(queueName, filteredTasks, {
336
+ job,
337
+ attempt: attempt + 1
338
+ });
339
+ } else if (this.logStatus) {
340
+ const statusKey = `${queueName}:${job}:`;
341
+ await this.setOne(statusKey + "err", Number(await this.getOne(statusKey + "err") || 0) + filteredTasks.length, this.logStatusTimeout);
342
+ await this.setOne(statusKey + "ready", Number(await this.getOne(statusKey + "ready") || 0) + filteredTasks.length, this.logStatusTimeout);
343
+ await this.addTasks(queueName + ":dlq", filteredTasks, {
344
+ job
345
+ });
346
+ }
336
347
  }
337
348
  } catch (err2) {
338
349
  throw new Error(`Batch error. ${err2.message}`);
@@ -452,8 +463,9 @@ var PowerQueues = class extends PowerRedis {
452
463
  }
453
464
  }
454
465
  }
466
+ let start = Date.now();
455
467
  if (!this.executeSync && promises.length > 0) {
456
- await Promise.all(promises.map((item) => item));
468
+ await Promise.all(promises.map((item) => item()));
457
469
  }
458
470
  await this.onBatchReady(queueName, result);
459
471
  if (!isArrFilled(result) && contended > tasks.length >> 1) {
@@ -532,26 +544,24 @@ var PowerQueues = class extends PowerRedis {
532
544
  return await this.onSuccess(queueName, task);
533
545
  }
534
546
  async error(err, queueName, task) {
535
- const dlqKey = queueName + ":dlq";
536
547
  const taskP = { ...task };
537
- if (taskP.attempt >= this.retryCount - 1) {
538
- const statusKey = `${queueName}:${taskP.job}:`;
539
- if (this.logStatus) {
540
- await this.incr(statusKey + "err", this.logStatusTimeout);
541
- await this.incr(statusKey + "ready", this.logStatusTimeout);
542
- }
543
- await this.addTasks(dlqKey, [{ ...taskP.payload }], {
544
- createdAt: taskP.createdAt,
545
- job: taskP.job,
546
- attempt: taskP.attempt
547
- });
548
- } else {
548
+ if (!(taskP.attempt >= this.retryCount - 1)) {
549
549
  await this.onRetry(err, queueName, taskP);
550
550
  await this.addTasks(queueName, [{ ...taskP.payload }], {
551
551
  createdAt: taskP.createdAt,
552
552
  job: taskP.job,
553
553
  attempt: (taskP.attempt || 0) + 1
554
554
  });
555
+ } else if (this.logStatus) {
556
+ const dlqKey = queueName + ":dlq";
557
+ const statusKey = `${queueName}:${taskP.job}:`;
558
+ await this.incr(statusKey + "err", this.logStatusTimeout);
559
+ await this.incr(statusKey + "ready", this.logStatusTimeout);
560
+ await this.addTasks(dlqKey, [{ ...taskP.payload }], {
561
+ createdAt: taskP.createdAt,
562
+ job: taskP.job,
563
+ attempt: taskP.attempt
564
+ });
555
565
  }
556
566
  return await this.onError(err, queueName, { ...taskP, attempt: (taskP.attempt || 0) + 1 });
557
567
  }
@@ -599,22 +609,21 @@ var PowerQueues = class extends PowerRedis {
599
609
  return;
600
610
  }
601
611
  const workerHeartbeatTimeoutMs = Math.max(1e3, Math.floor(Math.max(5e3, this.idemLockTimeout | 0) / 4));
602
- let timer;
603
- let alive = true;
604
- let hbFails = 0;
612
+ let timer, alive = true, hbFails = 0;
605
613
  const stop = () => {
606
614
  alive = false;
607
615
  if (timer) {
608
616
  clearTimeout(timer);
609
617
  }
610
618
  };
611
- const signal = this.signal();
612
- const onAbort = () => stop();
613
- signal?.addEventListener?.("abort", onAbort, { once: true });
614
619
  const tick = async () => {
615
620
  if (!alive) {
616
621
  return;
617
622
  }
623
+ if (this.signal()?.aborted) {
624
+ stop();
625
+ return;
626
+ }
618
627
  try {
619
628
  const ok = await this.sendHeartbeat(keys);
620
629
  hbFails = ok ? 0 : hbFails + 1;
@@ -633,10 +642,7 @@ var PowerQueues = class extends PowerRedis {
633
642
  };
634
643
  timer = setTimeout(tick, workerHeartbeatTimeoutMs);
635
644
  timer.unref?.();
636
- return () => {
637
- signal?.removeEventListener?.("abort", onAbort);
638
- stop();
639
- };
645
+ return () => stop();
640
646
  }
641
647
  async runScript(name, keys, args, defaultCode) {
642
648
  if (!this.scripts[name]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "power-queues",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
4
4
  "description": "High-performance Redis Streams queue for Node.js with Lua-powered bulk XADD, idempotent workers, heartbeat locks, stuck-task recovery, retries, DLQ, and distributed processing.",
5
5
  "author": "ihor-bielchenko",
6
6
  "license": "MIT",