power-queues 2.0.5 → 2.0.7

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