power-queues 2.0.5 → 2.0.6

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
@@ -264,8 +264,6 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
264
264
  this.scripts = {};
265
265
  this.addingBatchTasksCount = 800;
266
266
  this.addingBatchKeysLimit = 1e4;
267
- this.idemOn = true;
268
- this.idemKey = "";
269
267
  this.workerExecuteLockTimeoutMs = 18e4;
270
268
  this.workerCacheTaskTimeoutMs = 60;
271
269
  this.approveBatchTasksCount = 2e3;
@@ -280,11 +278,14 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
280
278
  this.recoveryStuckTasksTimeoutMs = 6e4;
281
279
  this.workerLoopIntervalMs = 5e3;
282
280
  this.workerSelectionTimeoutMs = 80;
281
+ this.workerMaxRetries = 5;
282
+ this.workerClearAttemptsTimeoutMs = 864e5;
283
+ this.workerStatusTimeoutMs = 864e5;
283
284
  }
284
285
  async onSelected(data) {
285
286
  return data;
286
287
  }
287
- async onExecute(id, payload, createdAt, job, key) {
288
+ async onExecute(id, payload, createdAt, job, key, attempt) {
288
289
  }
289
290
  async onExecuted(data) {
290
291
  }
@@ -309,6 +310,7 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
309
310
  await this.approve(ids);
310
311
  }
311
312
  } catch (err) {
313
+ await this.batchError(err);
312
314
  await (0, import_full_utils.wait)(600);
313
315
  }
314
316
  }
@@ -320,7 +322,8 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
320
322
  if (typeof queueName !== "string" || !(queueName.length > 0)) {
321
323
  throw new Error("Queue name is required.");
322
324
  }
323
- const batches = this.buildBatches(data);
325
+ const job = (0, import_uuid.v4)();
326
+ const batches = this.buildBatches(data, job, opts.idem);
324
327
  const result = new Array(data.length);
325
328
  const promises = [];
326
329
  let cursor = 0;
@@ -343,6 +346,16 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
343
346
  }
344
347
  }
345
348
  });
349
+ if (opts.status) {
350
+ await this.redis.set(`${queueName}:${job}:total`, data.length);
351
+ await this.redis.set(`${queueName}:${job}:ready`, 0);
352
+ await this.redis.set(`${queueName}:${job}:err`, 0);
353
+ await this.redis.set(`${queueName}:${job}:ok`, 0);
354
+ await this.redis.pexpire(`${queueName}:${job}:total`, this.workerStatusTimeoutMs);
355
+ await this.redis.pexpire(`${queueName}:${job}:ready`, this.workerStatusTimeoutMs);
356
+ await this.redis.pexpire(`${queueName}:${job}:err`, this.workerStatusTimeoutMs);
357
+ await this.redis.pexpire(`${queueName}:${job}:ok`, this.workerStatusTimeoutMs);
358
+ }
346
359
  await Promise.all(runners);
347
360
  return result;
348
361
  }
@@ -452,35 +465,32 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
452
465
  }
453
466
  return argv;
454
467
  }
455
- buildBatches(tasks) {
456
- const job = (0, import_uuid.v4)();
468
+ buildBatches(tasks, job, idem) {
457
469
  const batches = [];
458
470
  let batch = [], realKeysLength = 0;
459
471
  for (let task of tasks) {
472
+ const createdAt = task?.createdAt || Date.now();
460
473
  let entry = task;
461
- if (this.idemOn) {
462
- const createdAt = entry?.createdAt || Date.now();
463
- let idemKey = entry?.idemKey || (0, import_uuid.v4)();
464
- if (typeof entry.payload === "object") {
465
- if (this.idemKey && typeof entry.payload[this.idemKey] === "string" && entry.payload[this.idemKey].length > 0) {
466
- idemKey = entry.payload[this.idemKey];
474
+ if (typeof entry.payload === "object") {
475
+ entry = {
476
+ ...entry,
477
+ payload: {
478
+ payload: JSON.stringify(entry.payload),
479
+ createdAt,
480
+ job
467
481
  }
468
- entry = {
469
- ...entry,
470
- payload: {
471
- payload: JSON.stringify(entry.payload),
472
- createdAt,
473
- job,
474
- idemKey
475
- }
476
- };
477
- } else if (Array.isArray(entry.flat)) {
478
- entry.flat.push("createdAt");
479
- entry.flat.push(String(createdAt));
480
- entry.flat.push("job");
481
- entry.flat.push(job);
482
+ };
483
+ if (idem) {
484
+ entry.payload["idemKey"] = entry?.idemKey || (0, import_uuid.v4)();
485
+ }
486
+ } else if (Array.isArray(entry.flat)) {
487
+ entry.flat.push("createdAt");
488
+ entry.flat.push(String(createdAt));
489
+ entry.flat.push("job");
490
+ entry.flat.push(job);
491
+ if (idem) {
482
492
  entry.flat.push("idemKey");
483
- entry.flat.push(idemKey);
493
+ entry.flat.push(entry?.idemKey || (0, import_uuid.v4)());
484
494
  }
485
495
  }
486
496
  const reqKeysLength = this.keysLength(entry);
@@ -500,6 +510,33 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
500
510
  keysLength(task) {
501
511
  return 2 + ("flat" in task && Array.isArray(task.flat) && task.flat.length ? task.flat.length : Object.keys(task).length * 2);
502
512
  }
513
+ attemptsKey(id) {
514
+ const safeStream = this.stream.replace(/[^\w:\-]/g, "_");
515
+ const safeId = id.replace(/[^\w:\-]/g, "_");
516
+ return `q:${safeStream}:attempts:${safeId}`;
517
+ }
518
+ async incrAttempts(id) {
519
+ try {
520
+ const key = this.attemptsKey(id);
521
+ const attempts = await this.redis.incr(key);
522
+ await this.redis.pexpire(key, this.workerClearAttemptsTimeoutMs);
523
+ return attempts;
524
+ } catch (err) {
525
+ }
526
+ return 0;
527
+ }
528
+ async getAttempts(id) {
529
+ const key = this.attemptsKey(id);
530
+ const v = await this.redis.get(key);
531
+ return Number(v || 0);
532
+ }
533
+ async clearAttempts(id) {
534
+ const key = this.attemptsKey(id);
535
+ try {
536
+ await this.redis.del(key);
537
+ } catch (e) {
538
+ }
539
+ }
503
540
  async success(id, payload, createdAt, job, key) {
504
541
  if (this.executeJobStatus) {
505
542
  await this.status(id, payload, createdAt, job, key);
@@ -511,6 +548,18 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
511
548
  const { ready = 0, ok = 0 } = await this.getMany(prefix);
512
549
  await this.setMany([{ key: `${prefix}ready`, value: ready + 1 }, { key: `${prefix}ok`, value: ok + 1 }], this.executeJobStatusTtlSec);
513
550
  }
551
+ async batchError(err, tasks) {
552
+ }
553
+ async error(err, id, payload, createdAt, job, key) {
554
+ await this.onError(err, id, payload, createdAt, job, key);
555
+ }
556
+ async onError(err, id, payload, createdAt, job, key) {
557
+ }
558
+ async attempt(err, id, payload, createdAt, job, key, attempts) {
559
+ await this.onRetry(err, id, payload, createdAt, job, key, attempts);
560
+ }
561
+ async onRetry(err, id, payload, createdAt, job, key, attempts) {
562
+ }
514
563
  async execute(tasks) {
515
564
  const result = [];
516
565
  let contended = 0, promises = [];
@@ -542,6 +591,7 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
542
591
  await this.waitAbortable(15 + Math.floor(Math.random() * 35) + Math.min(250, 15 * contended + Math.floor(Math.random() * 40)));
543
592
  }
544
593
  } catch (err) {
594
+ await this.batchError(err, tasks);
545
595
  }
546
596
  return result;
547
597
  }
@@ -550,10 +600,27 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
550
600
  return await this.idempotency(id, payload, createdAt, job, key);
551
601
  } else {
552
602
  try {
553
- await this.onExecute(id, payload, createdAt, job, key);
603
+ await this.onExecute(id, payload, createdAt, job, key, await this.getAttempts(id));
554
604
  await this.success(id, payload, createdAt, job, key);
555
605
  return { id };
556
606
  } catch (err) {
607
+ const attempts = await this.incrAttempts(id);
608
+ await this.attempt(err, id, payload, createdAt, job, key, attempts);
609
+ await this.error(err, id, payload, createdAt, job, key);
610
+ if (attempts >= this.workerMaxRetries) {
611
+ await this.addTasks(`${this.stream}:dlq`, [{
612
+ payload: {
613
+ ...payload,
614
+ error: String(err?.message || err),
615
+ createdAt,
616
+ job,
617
+ id,
618
+ attempts
619
+ }
620
+ }]);
621
+ await this.clearAttempts(id);
622
+ return { id };
623
+ }
557
624
  }
558
625
  }
559
626
  return {};
@@ -593,12 +660,29 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
593
660
  const heartbeat = this.heartbeat(keys) || (() => {
594
661
  });
595
662
  try {
596
- await this.onExecute(id, payload, createdAt, job, key);
663
+ await this.onExecute(id, payload, createdAt, job, key, await this.getAttempts(id));
597
664
  await this.idempotencyDone(keys);
598
665
  await this.success(id, payload, createdAt, job, key);
599
666
  return { id };
600
667
  } catch (err) {
668
+ const attempts = await this.incrAttempts(id);
601
669
  try {
670
+ await this.attempt(err, id, payload, createdAt, job, key, attempts);
671
+ await this.error(err, id, payload, createdAt, job, key);
672
+ if (attempts >= this.workerMaxRetries) {
673
+ await this.addTasks(`${this.stream}:dlq`, [{
674
+ payload: {
675
+ ...payload,
676
+ error: String(err?.message || err),
677
+ createdAt,
678
+ job,
679
+ id
680
+ }
681
+ }]);
682
+ await this.clearAttempts(id);
683
+ await this.idempotencyFree(keys);
684
+ return { id };
685
+ }
602
686
  await this.idempotencyFree(keys);
603
687
  } catch (err2) {
604
688
  }
@@ -760,11 +844,10 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
760
844
  const id = Buffer.isBuffer(e?.[0]) ? e[0].toString() : e?.[0];
761
845
  const kvRaw = e?.[1] ?? [];
762
846
  const kv = Array.isArray(kvRaw) ? kvRaw.map((x) => Buffer.isBuffer(x) ? x.toString() : x) : [];
763
- return [id, kv, 0, "", ""];
847
+ return [id, kv];
764
848
  }).filter(([id, kv]) => typeof id === "string" && id.length > 0 && Array.isArray(kv) && (kv.length & 1) === 0).map(([id, kv]) => {
765
- const values = this.values(kv);
766
- const { idemKey = "", createdAt, job, ...data } = this.payload(values);
767
- return [id, data, createdAt, job, idemKey];
849
+ const { idemKey = "", job, createdAt, payload } = this.values(kv);
850
+ return [id, this.payload(payload), createdAt, job, idemKey];
768
851
  });
769
852
  }
770
853
  values(value) {
package/dist/index.d.cts CHANGED
@@ -13,6 +13,8 @@ type AddTasksOptions = {
13
13
  exact?: boolean;
14
14
  trimLimit?: number;
15
15
  id?: string;
16
+ status?: boolean;
17
+ idem?: boolean;
16
18
  };
17
19
  type Task = {
18
20
  job: string;
@@ -35,8 +37,6 @@ declare class PowerQueues extends PowerRedis {
35
37
  readonly scripts: Record<string, SavedScript>;
36
38
  readonly addingBatchTasksCount: number;
37
39
  readonly addingBatchKeysLimit: number;
38
- readonly idemOn: boolean;
39
- readonly idemKey: string;
40
40
  readonly workerExecuteLockTimeoutMs: number;
41
41
  readonly workerCacheTaskTimeoutMs: number;
42
42
  readonly approveBatchTasksCount: number;
@@ -51,8 +51,11 @@ declare class PowerQueues extends PowerRedis {
51
51
  readonly recoveryStuckTasksTimeoutMs: number;
52
52
  readonly workerLoopIntervalMs: number;
53
53
  readonly workerSelectionTimeoutMs: number;
54
+ readonly workerMaxRetries: number;
55
+ readonly workerClearAttemptsTimeoutMs: number;
56
+ readonly workerStatusTimeoutMs: number;
54
57
  onSelected(data: Array<[string, any[], number, string, string]>): Promise<[string, any[], number, string, string][]>;
55
- onExecute(id: string, payload: any, createdAt: number, job: string, key: string): Promise<void>;
58
+ onExecute(id: string, payload: any, createdAt: number, job: string, key: string, attempt: number): Promise<void>;
56
59
  onExecuted(data: Array<[string, any[], number, string, string]>): Promise<void>;
57
60
  onSuccess(id: string, payload: any, createdAt: number, job: string, key: string): Promise<void>;
58
61
  runQueue(): Promise<void>;
@@ -66,8 +69,17 @@ declare class PowerQueues extends PowerRedis {
66
69
  private payloadBatch;
67
70
  private buildBatches;
68
71
  private keysLength;
72
+ private attemptsKey;
73
+ private incrAttempts;
74
+ private getAttempts;
75
+ private clearAttempts;
69
76
  private success;
70
77
  private status;
78
+ private batchError;
79
+ private error;
80
+ onError(err: any, id: string, payload: any, createdAt: number, job: string, key: string): Promise<void>;
81
+ private attempt;
82
+ onRetry(err: any, id: string, payload: any, createdAt: number, job: string, key: string, attempts: number): Promise<void>;
71
83
  private execute;
72
84
  private executeProcess;
73
85
  private approve;
package/dist/index.d.ts CHANGED
@@ -13,6 +13,8 @@ type AddTasksOptions = {
13
13
  exact?: boolean;
14
14
  trimLimit?: number;
15
15
  id?: string;
16
+ status?: boolean;
17
+ idem?: boolean;
16
18
  };
17
19
  type Task = {
18
20
  job: string;
@@ -35,8 +37,6 @@ declare class PowerQueues extends PowerRedis {
35
37
  readonly scripts: Record<string, SavedScript>;
36
38
  readonly addingBatchTasksCount: number;
37
39
  readonly addingBatchKeysLimit: number;
38
- readonly idemOn: boolean;
39
- readonly idemKey: string;
40
40
  readonly workerExecuteLockTimeoutMs: number;
41
41
  readonly workerCacheTaskTimeoutMs: number;
42
42
  readonly approveBatchTasksCount: number;
@@ -51,8 +51,11 @@ declare class PowerQueues extends PowerRedis {
51
51
  readonly recoveryStuckTasksTimeoutMs: number;
52
52
  readonly workerLoopIntervalMs: number;
53
53
  readonly workerSelectionTimeoutMs: number;
54
+ readonly workerMaxRetries: number;
55
+ readonly workerClearAttemptsTimeoutMs: number;
56
+ readonly workerStatusTimeoutMs: number;
54
57
  onSelected(data: Array<[string, any[], number, string, string]>): Promise<[string, any[], number, string, string][]>;
55
- onExecute(id: string, payload: any, createdAt: number, job: string, key: string): Promise<void>;
58
+ onExecute(id: string, payload: any, createdAt: number, job: string, key: string, attempt: number): Promise<void>;
56
59
  onExecuted(data: Array<[string, any[], number, string, string]>): Promise<void>;
57
60
  onSuccess(id: string, payload: any, createdAt: number, job: string, key: string): Promise<void>;
58
61
  runQueue(): Promise<void>;
@@ -66,8 +69,17 @@ declare class PowerQueues extends PowerRedis {
66
69
  private payloadBatch;
67
70
  private buildBatches;
68
71
  private keysLength;
72
+ private attemptsKey;
73
+ private incrAttempts;
74
+ private getAttempts;
75
+ private clearAttempts;
69
76
  private success;
70
77
  private status;
78
+ private batchError;
79
+ private error;
80
+ onError(err: any, id: string, payload: any, createdAt: number, job: string, key: string): Promise<void>;
81
+ private attempt;
82
+ onRetry(err: any, id: string, payload: any, createdAt: number, job: string, key: string, attempts: number): Promise<void>;
71
83
  private execute;
72
84
  private executeProcess;
73
85
  private approve;
package/dist/index.js CHANGED
@@ -238,8 +238,6 @@ var PowerQueues = class extends PowerRedis {
238
238
  this.scripts = {};
239
239
  this.addingBatchTasksCount = 800;
240
240
  this.addingBatchKeysLimit = 1e4;
241
- this.idemOn = true;
242
- this.idemKey = "";
243
241
  this.workerExecuteLockTimeoutMs = 18e4;
244
242
  this.workerCacheTaskTimeoutMs = 60;
245
243
  this.approveBatchTasksCount = 2e3;
@@ -254,11 +252,14 @@ var PowerQueues = class extends PowerRedis {
254
252
  this.recoveryStuckTasksTimeoutMs = 6e4;
255
253
  this.workerLoopIntervalMs = 5e3;
256
254
  this.workerSelectionTimeoutMs = 80;
255
+ this.workerMaxRetries = 5;
256
+ this.workerClearAttemptsTimeoutMs = 864e5;
257
+ this.workerStatusTimeoutMs = 864e5;
257
258
  }
258
259
  async onSelected(data) {
259
260
  return data;
260
261
  }
261
- async onExecute(id, payload, createdAt, job, key) {
262
+ async onExecute(id, payload, createdAt, job, key, attempt) {
262
263
  }
263
264
  async onExecuted(data) {
264
265
  }
@@ -283,6 +284,7 @@ var PowerQueues = class extends PowerRedis {
283
284
  await this.approve(ids);
284
285
  }
285
286
  } catch (err) {
287
+ await this.batchError(err);
286
288
  await wait(600);
287
289
  }
288
290
  }
@@ -294,7 +296,8 @@ var PowerQueues = class extends PowerRedis {
294
296
  if (typeof queueName !== "string" || !(queueName.length > 0)) {
295
297
  throw new Error("Queue name is required.");
296
298
  }
297
- const batches = this.buildBatches(data);
299
+ const job = uuid();
300
+ const batches = this.buildBatches(data, job, opts.idem);
298
301
  const result = new Array(data.length);
299
302
  const promises = [];
300
303
  let cursor = 0;
@@ -317,6 +320,16 @@ var PowerQueues = class extends PowerRedis {
317
320
  }
318
321
  }
319
322
  });
323
+ if (opts.status) {
324
+ await this.redis.set(`${queueName}:${job}:total`, data.length);
325
+ await this.redis.set(`${queueName}:${job}:ready`, 0);
326
+ await this.redis.set(`${queueName}:${job}:err`, 0);
327
+ await this.redis.set(`${queueName}:${job}:ok`, 0);
328
+ await this.redis.pexpire(`${queueName}:${job}:total`, this.workerStatusTimeoutMs);
329
+ await this.redis.pexpire(`${queueName}:${job}:ready`, this.workerStatusTimeoutMs);
330
+ await this.redis.pexpire(`${queueName}:${job}:err`, this.workerStatusTimeoutMs);
331
+ await this.redis.pexpire(`${queueName}:${job}:ok`, this.workerStatusTimeoutMs);
332
+ }
320
333
  await Promise.all(runners);
321
334
  return result;
322
335
  }
@@ -426,35 +439,32 @@ var PowerQueues = class extends PowerRedis {
426
439
  }
427
440
  return argv;
428
441
  }
429
- buildBatches(tasks) {
430
- const job = uuid();
442
+ buildBatches(tasks, job, idem) {
431
443
  const batches = [];
432
444
  let batch = [], realKeysLength = 0;
433
445
  for (let task of tasks) {
446
+ const createdAt = task?.createdAt || Date.now();
434
447
  let entry = task;
435
- if (this.idemOn) {
436
- const createdAt = entry?.createdAt || Date.now();
437
- let idemKey = entry?.idemKey || uuid();
438
- if (typeof entry.payload === "object") {
439
- if (this.idemKey && typeof entry.payload[this.idemKey] === "string" && entry.payload[this.idemKey].length > 0) {
440
- idemKey = entry.payload[this.idemKey];
448
+ if (typeof entry.payload === "object") {
449
+ entry = {
450
+ ...entry,
451
+ payload: {
452
+ payload: JSON.stringify(entry.payload),
453
+ createdAt,
454
+ job
441
455
  }
442
- entry = {
443
- ...entry,
444
- payload: {
445
- payload: JSON.stringify(entry.payload),
446
- createdAt,
447
- job,
448
- idemKey
449
- }
450
- };
451
- } else if (Array.isArray(entry.flat)) {
452
- entry.flat.push("createdAt");
453
- entry.flat.push(String(createdAt));
454
- entry.flat.push("job");
455
- entry.flat.push(job);
456
+ };
457
+ if (idem) {
458
+ entry.payload["idemKey"] = entry?.idemKey || uuid();
459
+ }
460
+ } else if (Array.isArray(entry.flat)) {
461
+ entry.flat.push("createdAt");
462
+ entry.flat.push(String(createdAt));
463
+ entry.flat.push("job");
464
+ entry.flat.push(job);
465
+ if (idem) {
456
466
  entry.flat.push("idemKey");
457
- entry.flat.push(idemKey);
467
+ entry.flat.push(entry?.idemKey || uuid());
458
468
  }
459
469
  }
460
470
  const reqKeysLength = this.keysLength(entry);
@@ -474,6 +484,33 @@ var PowerQueues = class extends PowerRedis {
474
484
  keysLength(task) {
475
485
  return 2 + ("flat" in task && Array.isArray(task.flat) && task.flat.length ? task.flat.length : Object.keys(task).length * 2);
476
486
  }
487
+ attemptsKey(id) {
488
+ const safeStream = this.stream.replace(/[^\w:\-]/g, "_");
489
+ const safeId = id.replace(/[^\w:\-]/g, "_");
490
+ return `q:${safeStream}:attempts:${safeId}`;
491
+ }
492
+ async incrAttempts(id) {
493
+ try {
494
+ const key = this.attemptsKey(id);
495
+ const attempts = await this.redis.incr(key);
496
+ await this.redis.pexpire(key, this.workerClearAttemptsTimeoutMs);
497
+ return attempts;
498
+ } catch (err) {
499
+ }
500
+ return 0;
501
+ }
502
+ async getAttempts(id) {
503
+ const key = this.attemptsKey(id);
504
+ const v = await this.redis.get(key);
505
+ return Number(v || 0);
506
+ }
507
+ async clearAttempts(id) {
508
+ const key = this.attemptsKey(id);
509
+ try {
510
+ await this.redis.del(key);
511
+ } catch (e) {
512
+ }
513
+ }
477
514
  async success(id, payload, createdAt, job, key) {
478
515
  if (this.executeJobStatus) {
479
516
  await this.status(id, payload, createdAt, job, key);
@@ -485,6 +522,18 @@ var PowerQueues = class extends PowerRedis {
485
522
  const { ready = 0, ok = 0 } = await this.getMany(prefix);
486
523
  await this.setMany([{ key: `${prefix}ready`, value: ready + 1 }, { key: `${prefix}ok`, value: ok + 1 }], this.executeJobStatusTtlSec);
487
524
  }
525
+ async batchError(err, tasks) {
526
+ }
527
+ async error(err, id, payload, createdAt, job, key) {
528
+ await this.onError(err, id, payload, createdAt, job, key);
529
+ }
530
+ async onError(err, id, payload, createdAt, job, key) {
531
+ }
532
+ async attempt(err, id, payload, createdAt, job, key, attempts) {
533
+ await this.onRetry(err, id, payload, createdAt, job, key, attempts);
534
+ }
535
+ async onRetry(err, id, payload, createdAt, job, key, attempts) {
536
+ }
488
537
  async execute(tasks) {
489
538
  const result = [];
490
539
  let contended = 0, promises = [];
@@ -516,6 +565,7 @@ var PowerQueues = class extends PowerRedis {
516
565
  await this.waitAbortable(15 + Math.floor(Math.random() * 35) + Math.min(250, 15 * contended + Math.floor(Math.random() * 40)));
517
566
  }
518
567
  } catch (err) {
568
+ await this.batchError(err, tasks);
519
569
  }
520
570
  return result;
521
571
  }
@@ -524,10 +574,27 @@ var PowerQueues = class extends PowerRedis {
524
574
  return await this.idempotency(id, payload, createdAt, job, key);
525
575
  } else {
526
576
  try {
527
- await this.onExecute(id, payload, createdAt, job, key);
577
+ await this.onExecute(id, payload, createdAt, job, key, await this.getAttempts(id));
528
578
  await this.success(id, payload, createdAt, job, key);
529
579
  return { id };
530
580
  } catch (err) {
581
+ const attempts = await this.incrAttempts(id);
582
+ await this.attempt(err, id, payload, createdAt, job, key, attempts);
583
+ await this.error(err, id, payload, createdAt, job, key);
584
+ if (attempts >= this.workerMaxRetries) {
585
+ await this.addTasks(`${this.stream}:dlq`, [{
586
+ payload: {
587
+ ...payload,
588
+ error: String(err?.message || err),
589
+ createdAt,
590
+ job,
591
+ id,
592
+ attempts
593
+ }
594
+ }]);
595
+ await this.clearAttempts(id);
596
+ return { id };
597
+ }
531
598
  }
532
599
  }
533
600
  return {};
@@ -567,12 +634,29 @@ var PowerQueues = class extends PowerRedis {
567
634
  const heartbeat = this.heartbeat(keys) || (() => {
568
635
  });
569
636
  try {
570
- await this.onExecute(id, payload, createdAt, job, key);
637
+ await this.onExecute(id, payload, createdAt, job, key, await this.getAttempts(id));
571
638
  await this.idempotencyDone(keys);
572
639
  await this.success(id, payload, createdAt, job, key);
573
640
  return { id };
574
641
  } catch (err) {
642
+ const attempts = await this.incrAttempts(id);
575
643
  try {
644
+ await this.attempt(err, id, payload, createdAt, job, key, attempts);
645
+ await this.error(err, id, payload, createdAt, job, key);
646
+ if (attempts >= this.workerMaxRetries) {
647
+ await this.addTasks(`${this.stream}:dlq`, [{
648
+ payload: {
649
+ ...payload,
650
+ error: String(err?.message || err),
651
+ createdAt,
652
+ job,
653
+ id
654
+ }
655
+ }]);
656
+ await this.clearAttempts(id);
657
+ await this.idempotencyFree(keys);
658
+ return { id };
659
+ }
576
660
  await this.idempotencyFree(keys);
577
661
  } catch (err2) {
578
662
  }
@@ -734,11 +818,10 @@ var PowerQueues = class extends PowerRedis {
734
818
  const id = Buffer.isBuffer(e?.[0]) ? e[0].toString() : e?.[0];
735
819
  const kvRaw = e?.[1] ?? [];
736
820
  const kv = Array.isArray(kvRaw) ? kvRaw.map((x) => Buffer.isBuffer(x) ? x.toString() : x) : [];
737
- return [id, kv, 0, "", ""];
821
+ return [id, kv];
738
822
  }).filter(([id, kv]) => typeof id === "string" && id.length > 0 && Array.isArray(kv) && (kv.length & 1) === 0).map(([id, kv]) => {
739
- const values = this.values(kv);
740
- const { idemKey = "", createdAt, job, ...data } = this.payload(values);
741
- return [id, data, createdAt, job, idemKey];
823
+ const { idemKey = "", job, createdAt, payload } = this.values(kv);
824
+ return [id, this.payload(payload), createdAt, job, idemKey];
742
825
  });
743
826
  }
744
827
  values(value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "power-queues",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "Base classes for implementing custom queues in redis under high load conditions based on nestjs.",
5
5
  "author": "ihor-bielchenko",
6
6
  "license": "MIT",