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 +38 -32
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +38 -32
- package/package.json +1 -1
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 =
|
|
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 =
|
|
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
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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:
|
|
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:
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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
|
+
"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",
|