power-queues 2.0.22 → 2.1.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/dist/index.cjs +373 -429
- package/dist/index.d.cts +50 -62
- package/dist/index.d.ts +50 -62
- package/dist/index.js +374 -430
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -269,315 +269,191 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
|
|
|
269
269
|
super(...arguments);
|
|
270
270
|
this.abort = new AbortController();
|
|
271
271
|
this.scripts = {};
|
|
272
|
-
this.
|
|
273
|
-
this.
|
|
274
|
-
this.
|
|
275
|
-
this.
|
|
276
|
-
this.
|
|
272
|
+
this.host = "host";
|
|
273
|
+
this.group = "gr1";
|
|
274
|
+
this.selectStuckCount = 200;
|
|
275
|
+
this.selectStuckTimeout = 6e4;
|
|
276
|
+
this.selectStuckMaxTimeout = 80;
|
|
277
|
+
this.selectCount = 200;
|
|
278
|
+
this.selectTimeout = 5e3;
|
|
279
|
+
this.buildBatchCount = 800;
|
|
280
|
+
this.buildBatchMaxCount = 1e4;
|
|
281
|
+
this.retryCount = 1;
|
|
282
|
+
this.executeSync = false;
|
|
283
|
+
this.idemLockTimeout = 18e4;
|
|
284
|
+
this.idemDoneTimeout = 6e4;
|
|
285
|
+
this.logStatus = false;
|
|
286
|
+
this.logStatusTimeout = 3e5;
|
|
287
|
+
this.approveCount = 2e3;
|
|
277
288
|
this.removeOnExecuted = false;
|
|
278
|
-
this.executeBatchAtOnce = false;
|
|
279
|
-
this.executeJobStatus = false;
|
|
280
|
-
this.executeJobStatusTtlMs = 3e5;
|
|
281
|
-
this.consumerHost = "host";
|
|
282
|
-
this.stream = "stream";
|
|
283
|
-
this.group = "group";
|
|
284
|
-
this.workerBatchTasksCount = 200;
|
|
285
|
-
this.recoveryStuckTasksTimeoutMs = 6e4;
|
|
286
|
-
this.workerLoopIntervalMs = 5e3;
|
|
287
|
-
this.workerSelectionTimeoutMs = 80;
|
|
288
|
-
this.workerMaxRetries = 1;
|
|
289
|
-
this.workerClearAttemptsTimeoutMs = 864e5;
|
|
290
|
-
}
|
|
291
|
-
async onSelected(data) {
|
|
292
|
-
return data;
|
|
293
|
-
}
|
|
294
|
-
async onExecute(id, payload, createdAt, job, key, attempt) {
|
|
295
|
-
}
|
|
296
|
-
async onReady(data) {
|
|
297
|
-
}
|
|
298
|
-
async onSuccess(id, payload, createdAt, job, key) {
|
|
299
289
|
}
|
|
300
|
-
|
|
290
|
+
signal() {
|
|
291
|
+
return this.abort.signal;
|
|
301
292
|
}
|
|
302
|
-
|
|
293
|
+
consumer() {
|
|
294
|
+
return this.host + ":" + process.pid;
|
|
303
295
|
}
|
|
304
|
-
async
|
|
296
|
+
async runQueue(queueName, from = "0-0") {
|
|
297
|
+
await this.createGroup(queueName, from);
|
|
298
|
+
await this.consumerLoop(queueName, from);
|
|
305
299
|
}
|
|
306
|
-
async
|
|
307
|
-
|
|
308
|
-
|
|
300
|
+
async createGroup(queueName, from = "0-0") {
|
|
301
|
+
try {
|
|
302
|
+
await this.redis.xgroup("CREATE", queueName, this.group, from, "MKSTREAM");
|
|
303
|
+
} catch (err) {
|
|
304
|
+
const msg = String(err?.message || "");
|
|
305
|
+
if (!msg.includes("BUSYGROUP")) {
|
|
306
|
+
throw err;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
309
|
}
|
|
310
|
-
async consumerLoop() {
|
|
310
|
+
async consumerLoop(queueName, from = "0-0") {
|
|
311
311
|
const signal = this.signal();
|
|
312
312
|
while (!signal?.aborted) {
|
|
313
|
+
let tasks = [];
|
|
313
314
|
try {
|
|
314
|
-
|
|
315
|
-
if (!(0, import_full_utils.isArrFilled)(tasks)) {
|
|
316
|
-
await (0, import_full_utils.wait)(600);
|
|
317
|
-
continue;
|
|
318
|
-
}
|
|
319
|
-
const tasksP = await this.onSelected(tasks);
|
|
320
|
-
const ids = await this.execute((0, import_full_utils.isArrFilled)(tasksP) ? tasksP : tasks);
|
|
321
|
-
if ((0, import_full_utils.isArrFilled)(ids)) {
|
|
322
|
-
await this.approve(ids);
|
|
323
|
-
}
|
|
315
|
+
tasks = await this.select(queueName, from);
|
|
324
316
|
} catch (err) {
|
|
325
|
-
|
|
326
|
-
|
|
317
|
+
}
|
|
318
|
+
if (!(0, import_full_utils.isArrFilled)(tasks)) {
|
|
319
|
+
await (0, import_full_utils.wait)(400);
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
try {
|
|
323
|
+
await this.approve(queueName, await this.execute(queueName, await this.beforeExecute(queueName, tasks)));
|
|
324
|
+
} catch (err) {
|
|
325
|
+
await this.batchError(err, queueName, tasks);
|
|
326
|
+
try {
|
|
327
|
+
await this.approve(queueName, tasks.map((task) => task[0]));
|
|
328
|
+
} catch {
|
|
329
|
+
}
|
|
330
|
+
await (0, import_full_utils.wait)(400);
|
|
327
331
|
}
|
|
328
332
|
}
|
|
329
333
|
}
|
|
330
|
-
async
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const job = opts.id ?? (0, import_uuid.v4)();
|
|
338
|
-
const batches = this.buildBatches(data, job, opts.idem);
|
|
339
|
-
const result = new Array(data.length);
|
|
340
|
-
const promises = [];
|
|
341
|
-
let cursor = 0;
|
|
342
|
-
for (const batch of batches) {
|
|
343
|
-
const start = cursor;
|
|
344
|
-
const end = start + batch.length;
|
|
345
|
-
cursor = end;
|
|
346
|
-
promises.push(async () => {
|
|
347
|
-
const partIds = await this.xaddBatch(queueName, ...this.payloadBatch(batch, opts));
|
|
348
|
-
for (let k = 0; k < partIds.length; k++) {
|
|
349
|
-
result[start + k] = partIds[k];
|
|
334
|
+
async batchError(err, queueName, tasks) {
|
|
335
|
+
try {
|
|
336
|
+
const filtered = {};
|
|
337
|
+
tasks.forEach((task, index) => {
|
|
338
|
+
const key = String(task[5] + ":" + task[2] + ":" + task[3]);
|
|
339
|
+
if (!filtered[key]) {
|
|
340
|
+
filtered[key] = [];
|
|
350
341
|
}
|
|
342
|
+
filtered[key].push(tasks[index]);
|
|
351
343
|
});
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
344
|
+
for (let key in filtered) {
|
|
345
|
+
const filteredTasks = filtered[key];
|
|
346
|
+
const keySplit = key.split(":");
|
|
347
|
+
const attempt = Number(keySplit[0]);
|
|
348
|
+
await this.addTasks(queueName + (attempt + 1 >= this.retryCount ? ":dlq" : ""), filteredTasks.map((task) => ({ ...task[1] })), {
|
|
349
|
+
createdAt: Number(keySplit[1]),
|
|
350
|
+
job: keySplit[2],
|
|
351
|
+
attempt: attempt + 1
|
|
352
|
+
});
|
|
359
353
|
}
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
await this.redis.set(`${queueName}:${job}:total`, data.length);
|
|
363
|
-
await this.redis.pexpire(`${queueName}:${job}:total`, opts.statusTimeoutMs || 3e5);
|
|
354
|
+
} catch (err2) {
|
|
355
|
+
throw new Error(`Batch error. ${err2.message}`);
|
|
364
356
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const scripts = full ? [
|
|
370
|
-
["XAddBulk", XAddBulk],
|
|
371
|
-
["Approve", Approve],
|
|
372
|
-
["IdempotencyAllow", IdempotencyAllow],
|
|
373
|
-
["IdempotencyStart", IdempotencyStart],
|
|
374
|
-
["IdempotencyDone", IdempotencyDone],
|
|
375
|
-
["IdempotencyFree", IdempotencyFree],
|
|
376
|
-
["SelectStuck", SelectStuck]
|
|
377
|
-
] : [
|
|
378
|
-
["XAddBulk", XAddBulk]
|
|
379
|
-
];
|
|
380
|
-
for (const [name, code] of scripts) {
|
|
381
|
-
await this.loadScript(this.saveScript(name, code));
|
|
357
|
+
try {
|
|
358
|
+
await this.onBatchError(err, queueName, tasks);
|
|
359
|
+
} catch (err2) {
|
|
360
|
+
throw new Error(`Batch error. ${err2.message}`);
|
|
382
361
|
}
|
|
383
362
|
}
|
|
384
|
-
async
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
return await this.redis.script("LOAD", code);
|
|
388
|
-
} catch (e) {
|
|
389
|
-
if (i === 2) {
|
|
390
|
-
throw e;
|
|
391
|
-
}
|
|
392
|
-
await new Promise((r) => setTimeout(r, 10 + Math.floor(Math.random() * 40)));
|
|
393
|
-
}
|
|
363
|
+
async approve(queueName, ids) {
|
|
364
|
+
if (!(0, import_full_utils.isArrFilled)(ids)) {
|
|
365
|
+
return 0;
|
|
394
366
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
367
|
+
const approveCount = Math.max(500, Math.min(4e3, this.approveCount));
|
|
368
|
+
let total = 0, i = 0;
|
|
369
|
+
while (i < ids.length) {
|
|
370
|
+
const room = Math.min(approveCount, ids.length - i);
|
|
371
|
+
const part = ids.slice(i, i + room);
|
|
372
|
+
const approved = await this.runScript("Approve", [queueName], [this.group, this.removeOnExecuted ? "1" : "0", ...part], Approve);
|
|
373
|
+
total += Number(approved || 0);
|
|
374
|
+
i += room;
|
|
400
375
|
}
|
|
401
|
-
|
|
402
|
-
return codeBody;
|
|
376
|
+
return total;
|
|
403
377
|
}
|
|
404
|
-
async
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
this.saveScript(name, defaultCode);
|
|
410
|
-
}
|
|
411
|
-
if (!this.scripts[name].codeReady) {
|
|
412
|
-
this.scripts[name].codeReady = await this.loadScript(this.scripts[name].codeBody);
|
|
378
|
+
async select(queueName, from = "0-0") {
|
|
379
|
+
let selected = await this.selectS(queueName, from);
|
|
380
|
+
if (!(0, import_full_utils.isArrFilled)(selected)) {
|
|
381
|
+
selected = await this.selectF(queueName, from);
|
|
413
382
|
}
|
|
383
|
+
return this.selectP(selected);
|
|
384
|
+
}
|
|
385
|
+
async selectS(queueName, from = "0-0") {
|
|
414
386
|
try {
|
|
415
|
-
|
|
387
|
+
const res = await this.runScript("SelectStuck", [queueName], [this.group, this.consumer(), String(this.selectStuckTimeout), String(this.selectStuckCount), String(this.selectStuckMaxTimeout)], SelectStuck);
|
|
388
|
+
return (0, import_full_utils.isArr)(res) ? res : [];
|
|
416
389
|
} catch (err) {
|
|
417
|
-
if (String(err?.message || "").includes("
|
|
418
|
-
|
|
419
|
-
return await this.redis.evalsha(this.scripts[name].codeReady, keys.length, ...keys, ...args);
|
|
390
|
+
if (String(err?.message || "").includes("NOGROUP")) {
|
|
391
|
+
await this.createGroup(queueName, from);
|
|
420
392
|
}
|
|
421
|
-
throw err;
|
|
422
393
|
}
|
|
394
|
+
return [];
|
|
423
395
|
}
|
|
424
|
-
async
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
String(minidWindowMs),
|
|
443
|
-
String(minidExact)
|
|
444
|
-
];
|
|
445
|
-
for (const item of data) {
|
|
446
|
-
const entry = item;
|
|
447
|
-
const id = entry.id ?? "*";
|
|
448
|
-
let flat;
|
|
449
|
-
if ("flat" in entry && (0, import_full_utils.isArrFilled)(entry.flat)) {
|
|
450
|
-
flat = entry.flat;
|
|
451
|
-
if (flat.length % 2 !== 0) {
|
|
452
|
-
throw new Error('Property "flat" must contain an even number of realKeysLength (field/value pairs).');
|
|
453
|
-
}
|
|
454
|
-
} else if ("payload" in entry && (0, import_full_utils.isObjFilled)(entry.payload)) {
|
|
455
|
-
flat = [];
|
|
456
|
-
for (const [k, v] of Object.entries(entry.payload)) {
|
|
457
|
-
flat.push(k, v);
|
|
458
|
-
}
|
|
459
|
-
} else {
|
|
460
|
-
throw new Error('Task must have "payload" or "flat".');
|
|
461
|
-
}
|
|
462
|
-
const pairs = flat.length / 2;
|
|
463
|
-
if ((0, import_full_utils.isNumNZ)(pairs)) {
|
|
464
|
-
throw new Error('Task "flat" must contain at least one field/value pair.');
|
|
396
|
+
async selectF(queueName, from = "0-0") {
|
|
397
|
+
let rows = [];
|
|
398
|
+
try {
|
|
399
|
+
const res = await this.redis.xreadgroup(
|
|
400
|
+
"GROUP",
|
|
401
|
+
this.group,
|
|
402
|
+
this.consumer(),
|
|
403
|
+
"BLOCK",
|
|
404
|
+
Math.max(2, this.selectTimeout | 0),
|
|
405
|
+
"COUNT",
|
|
406
|
+
this.selectCount,
|
|
407
|
+
"STREAMS",
|
|
408
|
+
queueName,
|
|
409
|
+
">"
|
|
410
|
+
);
|
|
411
|
+
rows = res?.[0]?.[1] ?? [];
|
|
412
|
+
if (!(0, import_full_utils.isArrFilled)(rows)) {
|
|
413
|
+
return [];
|
|
465
414
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
argv.push(!token ? "" : (0, import_full_utils.isStrFilled)(token) ? token : String(token));
|
|
415
|
+
} catch (err) {
|
|
416
|
+
if (String(err?.message || "").includes("NOGROUP")) {
|
|
417
|
+
await this.createGroup(queueName, from);
|
|
470
418
|
}
|
|
471
419
|
}
|
|
472
|
-
return
|
|
420
|
+
return rows;
|
|
473
421
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
for (let task of tasks) {
|
|
478
|
-
const createdAt = task?.createdAt || Date.now();
|
|
479
|
-
let entry = task;
|
|
480
|
-
if ((0, import_full_utils.isObj)(entry.payload)) {
|
|
481
|
-
entry = {
|
|
482
|
-
...entry,
|
|
483
|
-
payload: {
|
|
484
|
-
payload: JSON.stringify(entry.payload),
|
|
485
|
-
createdAt,
|
|
486
|
-
job
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
if (idem) {
|
|
490
|
-
entry.payload["idemKey"] = entry?.idemKey || (0, import_uuid.v4)();
|
|
491
|
-
}
|
|
492
|
-
} else if (Array.isArray(entry.flat)) {
|
|
493
|
-
entry.flat.push("createdAt");
|
|
494
|
-
entry.flat.push(String(createdAt));
|
|
495
|
-
entry.flat.push("job");
|
|
496
|
-
entry.flat.push(job);
|
|
497
|
-
if (idem) {
|
|
498
|
-
entry.flat.push("idemKey");
|
|
499
|
-
entry.flat.push(entry?.idemKey || (0, import_uuid.v4)());
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
const reqKeysLength = this.keysLength(entry);
|
|
503
|
-
if (batch.length && (batch.length >= this.addingBatchTasksCount || realKeysLength + reqKeysLength > this.addingBatchKeysLimit)) {
|
|
504
|
-
batches.push(batch);
|
|
505
|
-
batch = [];
|
|
506
|
-
realKeysLength = 0;
|
|
507
|
-
}
|
|
508
|
-
batch.push(entry);
|
|
509
|
-
realKeysLength += reqKeysLength;
|
|
510
|
-
}
|
|
511
|
-
if (batch.length) {
|
|
512
|
-
batches.push(batch);
|
|
422
|
+
selectP(raw) {
|
|
423
|
+
if (!Array.isArray(raw)) {
|
|
424
|
+
return [];
|
|
513
425
|
}
|
|
514
|
-
return
|
|
426
|
+
return Array.from(raw || []).map((e) => {
|
|
427
|
+
const id = Buffer.isBuffer(e?.[0]) ? e[0].toString() : e?.[0];
|
|
428
|
+
const kvRaw = e?.[1] ?? [];
|
|
429
|
+
const kv = (0, import_full_utils.isArr)(kvRaw) ? kvRaw.map((x) => Buffer.isBuffer(x) ? x.toString() : x) : [];
|
|
430
|
+
return [id, kv];
|
|
431
|
+
}).filter(([id, kv]) => (0, import_full_utils.isStrFilled)(id) && (0, import_full_utils.isArr)(kv) && (kv.length & 1) === 0).map(([id, kv]) => {
|
|
432
|
+
const { payload, createdAt, job, idemKey = "", attempt } = this.values(kv);
|
|
433
|
+
return [id, this.payload(payload), createdAt, job, idemKey, Number(attempt)];
|
|
434
|
+
});
|
|
515
435
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
if ("payload" in task && (0, import_full_utils.isObj)(task.payload)) {
|
|
521
|
-
return 2 + Object.keys(task.payload).length * 2;
|
|
436
|
+
values(value) {
|
|
437
|
+
const result = {};
|
|
438
|
+
for (let i = 0; i < value.length; i += 2) {
|
|
439
|
+
result[value[i]] = value[i + 1];
|
|
522
440
|
}
|
|
523
|
-
return
|
|
524
|
-
}
|
|
525
|
-
attemptsKey(id) {
|
|
526
|
-
const safeStream = this.stream.replace(/[^\w:\-]/g, "_");
|
|
527
|
-
const safeId = id.replace(/[^\w:\-]/g, "_");
|
|
528
|
-
return `q:${safeStream}:attempts:${safeId}`;
|
|
441
|
+
return result;
|
|
529
442
|
}
|
|
530
|
-
|
|
443
|
+
payload(data) {
|
|
531
444
|
try {
|
|
532
|
-
|
|
533
|
-
const attempts = await this.redis.incr(key);
|
|
534
|
-
await this.redis.pexpire(key, this.workerClearAttemptsTimeoutMs);
|
|
535
|
-
return attempts;
|
|
445
|
+
return JSON.parse(data);
|
|
536
446
|
} catch (err) {
|
|
537
447
|
}
|
|
538
|
-
return
|
|
539
|
-
}
|
|
540
|
-
async getAttempts(id) {
|
|
541
|
-
const key = this.attemptsKey(id);
|
|
542
|
-
const v = await this.redis.get(key);
|
|
543
|
-
return Number(v || 0);
|
|
544
|
-
}
|
|
545
|
-
async clearAttempts(id) {
|
|
546
|
-
const key = this.attemptsKey(id);
|
|
547
|
-
try {
|
|
548
|
-
await this.redis.del(key);
|
|
549
|
-
} catch (e) {
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
async success(id, payload, createdAt, job, key) {
|
|
553
|
-
if (this.executeJobStatus) {
|
|
554
|
-
const prefix = `${this.stream}:${job}:`;
|
|
555
|
-
await this.incr(`${prefix}ok`, this.executeJobStatusTtlMs);
|
|
556
|
-
await this.incr(`${prefix}ready`, this.executeJobStatusTtlMs);
|
|
557
|
-
}
|
|
558
|
-
await this.onSuccess(id, payload, createdAt, job, key);
|
|
559
|
-
}
|
|
560
|
-
async batchError(err, tasks) {
|
|
561
|
-
await this.onBatchError(err, tasks);
|
|
562
|
-
}
|
|
563
|
-
async error(err, id, payload, createdAt, job, key, attempt) {
|
|
564
|
-
if (this.executeJobStatus && attempt >= this.workerMaxRetries) {
|
|
565
|
-
const prefix = `${this.stream}:${job}:`;
|
|
566
|
-
await this.incr(`${prefix}err`, this.executeJobStatusTtlMs);
|
|
567
|
-
await this.incr(`${prefix}ready`, this.executeJobStatusTtlMs);
|
|
568
|
-
}
|
|
569
|
-
await this.onError(err, id, payload, createdAt, job, key);
|
|
570
|
-
}
|
|
571
|
-
async attempt(err, id, payload, createdAt, job, key, attempt) {
|
|
572
|
-
await this.onRetry(err, id, payload, createdAt, job, key, attempt);
|
|
448
|
+
return data;
|
|
573
449
|
}
|
|
574
|
-
async execute(tasks) {
|
|
450
|
+
async execute(queueName, tasks) {
|
|
575
451
|
const result = [];
|
|
576
452
|
let contended = 0, promises = [];
|
|
577
|
-
for (const [id, payload, createdAt, job, idemKey] of tasks) {
|
|
578
|
-
if (this.
|
|
453
|
+
for (const [id, payload, createdAt, job, idemKey, attempt] of tasks) {
|
|
454
|
+
if (!this.executeSync) {
|
|
579
455
|
promises.push((async () => {
|
|
580
|
-
const r = await this.executeProcess(id, payload, createdAt, job, idemKey);
|
|
456
|
+
const r = await this.executeProcess(queueName, { id, payload, createdAt, job, idemKey, attempt });
|
|
581
457
|
if (r.id) {
|
|
582
458
|
result.push(id);
|
|
583
459
|
} else if (r.contended) {
|
|
@@ -585,7 +461,7 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
|
|
|
585
461
|
}
|
|
586
462
|
})());
|
|
587
463
|
} else {
|
|
588
|
-
const r = await this.executeProcess(id, payload, createdAt, job, idemKey);
|
|
464
|
+
const r = await this.executeProcess(queueName, { id, payload, createdAt, job, idemKey, attempt });
|
|
589
465
|
if (r.id) {
|
|
590
466
|
result.push(id);
|
|
591
467
|
} else if (r.contended) {
|
|
@@ -593,69 +469,20 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
|
|
|
593
469
|
}
|
|
594
470
|
}
|
|
595
471
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
await Promise.all(promises);
|
|
599
|
-
}
|
|
600
|
-
await this.onReady(tasks);
|
|
601
|
-
if (!(0, import_full_utils.isArrFilled)(result) && contended > tasks.length >> 1) {
|
|
602
|
-
await this.waitAbortable(15 + Math.floor(Math.random() * 35) + Math.min(250, 15 * contended + Math.floor(Math.random() * 40)));
|
|
603
|
-
}
|
|
604
|
-
} catch (err) {
|
|
605
|
-
await this.batchError(err, tasks);
|
|
606
|
-
}
|
|
607
|
-
return result;
|
|
608
|
-
}
|
|
609
|
-
async executeProcess(id, payload, createdAt, job, key) {
|
|
610
|
-
if (key) {
|
|
611
|
-
return await this.idempotency(id, payload, createdAt, job, key);
|
|
612
|
-
} else {
|
|
613
|
-
try {
|
|
614
|
-
await this.onExecute(id, payload, createdAt, job, key, await this.getAttempts(id));
|
|
615
|
-
await this.success(id, payload, createdAt, job, key);
|
|
616
|
-
return { id };
|
|
617
|
-
} catch (err) {
|
|
618
|
-
const attempt = await this.incrAttempts(id);
|
|
619
|
-
await this.attempt(err, id, payload, createdAt, job, key, attempt);
|
|
620
|
-
await this.error(err, id, payload, createdAt, job, key, attempt);
|
|
621
|
-
if (attempt >= this.workerMaxRetries) {
|
|
622
|
-
await this.addTasks(`${this.stream}:dlq`, [{
|
|
623
|
-
payload: {
|
|
624
|
-
...payload,
|
|
625
|
-
error: String(err?.message || err),
|
|
626
|
-
createdAt,
|
|
627
|
-
job,
|
|
628
|
-
id,
|
|
629
|
-
attempt
|
|
630
|
-
}
|
|
631
|
-
}]);
|
|
632
|
-
await this.clearAttempts(id);
|
|
633
|
-
return { id };
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
return {};
|
|
638
|
-
}
|
|
639
|
-
async approve(ids) {
|
|
640
|
-
if (!Array.isArray(ids) || !(ids.length > 0)) {
|
|
641
|
-
return 0;
|
|
472
|
+
if (!this.executeSync && promises.length > 0) {
|
|
473
|
+
await Promise.all(promises);
|
|
642
474
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
const room = Math.min(approveBatchTasksCount, ids.length - i);
|
|
647
|
-
const part = ids.slice(i, i + room);
|
|
648
|
-
const approved = await this.runScript("Approve", [this.stream], [this.group, this.removeOnExecuted ? "1" : "0", ...part], Approve);
|
|
649
|
-
total += Number(approved || 0);
|
|
650
|
-
i += room;
|
|
475
|
+
await this.onBatchSuccess(queueName, tasks);
|
|
476
|
+
if (!(0, import_full_utils.isArrFilled)(result) && contended > tasks.length >> 1) {
|
|
477
|
+
await this.waitAbortable(15 + Math.floor(Math.random() * 35) + Math.min(250, 15 * contended + Math.floor(Math.random() * 40)));
|
|
651
478
|
}
|
|
652
|
-
return
|
|
479
|
+
return result;
|
|
653
480
|
}
|
|
654
|
-
async
|
|
655
|
-
const keys = this.idempotencyKeys(
|
|
481
|
+
async executeProcess(queueName, task) {
|
|
482
|
+
const keys = this.idempotencyKeys(queueName, String(task.idemKey));
|
|
656
483
|
const allow = await this.idempotencyAllow(keys);
|
|
657
484
|
if (allow === 1) {
|
|
658
|
-
return { id };
|
|
485
|
+
return { id: task.id };
|
|
659
486
|
} else if (allow === 0) {
|
|
660
487
|
let ttl = -2;
|
|
661
488
|
try {
|
|
@@ -671,29 +498,17 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
|
|
|
671
498
|
const heartbeat = this.heartbeat(keys) || (() => {
|
|
672
499
|
});
|
|
673
500
|
try {
|
|
674
|
-
await this.onExecute(
|
|
501
|
+
await this.onExecute(queueName, task);
|
|
675
502
|
await this.idempotencyDone(keys);
|
|
676
|
-
await this.success(
|
|
677
|
-
return { id };
|
|
503
|
+
await this.success(queueName, task);
|
|
504
|
+
return { id: task.id };
|
|
678
505
|
} catch (err) {
|
|
679
|
-
const attempt = await this.incrAttempts(id);
|
|
680
506
|
try {
|
|
681
|
-
|
|
682
|
-
await this.error(err,
|
|
683
|
-
if (attempt >= this.
|
|
684
|
-
await this.addTasks(`${this.stream}:dlq`, [{
|
|
685
|
-
payload: {
|
|
686
|
-
...payload,
|
|
687
|
-
error: String(err?.message || err),
|
|
688
|
-
createdAt,
|
|
689
|
-
job,
|
|
690
|
-
id,
|
|
691
|
-
attempt: 0
|
|
692
|
-
}
|
|
693
|
-
}]);
|
|
694
|
-
await this.clearAttempts(id);
|
|
507
|
+
task.attempt = task.attempt + 1;
|
|
508
|
+
await this.error(err, queueName, task);
|
|
509
|
+
if (task.attempt >= this.retryCount) {
|
|
695
510
|
await this.idempotencyFree(keys);
|
|
696
|
-
return { id };
|
|
511
|
+
return { id: task.id };
|
|
697
512
|
}
|
|
698
513
|
await this.idempotencyFree(keys);
|
|
699
514
|
} catch (err2) {
|
|
@@ -702,8 +517,8 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
|
|
|
702
517
|
heartbeat();
|
|
703
518
|
}
|
|
704
519
|
}
|
|
705
|
-
idempotencyKeys(key) {
|
|
706
|
-
const prefix = `q:${
|
|
520
|
+
idempotencyKeys(queueName, key) {
|
|
521
|
+
const prefix = `q:${queueName.replace(/[^\w:\-]/g, "_")}:`;
|
|
707
522
|
const keyP = key.replace(/[^\w:\-]/g, "_");
|
|
708
523
|
const doneKey = `${prefix}done:${keyP}`;
|
|
709
524
|
const lockKey = `${prefix}lock:${keyP}`;
|
|
@@ -718,72 +533,50 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
|
|
|
718
533
|
};
|
|
719
534
|
}
|
|
720
535
|
async idempotencyAllow(keys) {
|
|
721
|
-
const res = await this.runScript("IdempotencyAllow", [keys.doneKey, keys.lockKey, keys.startKey], [String(this.
|
|
536
|
+
const res = await this.runScript("IdempotencyAllow", [keys.doneKey, keys.lockKey, keys.startKey], [String(this.idemLockTimeout), keys.token], IdempotencyAllow);
|
|
722
537
|
return Number(res || 0);
|
|
723
538
|
}
|
|
724
539
|
async idempotencyStart(keys) {
|
|
725
|
-
const res = await this.runScript("IdempotencyStart", [keys.lockKey, keys.startKey], [keys.token, String(this.
|
|
540
|
+
const res = await this.runScript("IdempotencyStart", [keys.lockKey, keys.startKey], [keys.token, String(this.idemLockTimeout)], IdempotencyStart);
|
|
726
541
|
return Number(res || 0) === 1;
|
|
727
542
|
}
|
|
728
543
|
async idempotencyDone(keys) {
|
|
729
|
-
await this.runScript("IdempotencyDone", [keys.doneKey, keys.lockKey, keys.startKey], [String(this.
|
|
544
|
+
await this.runScript("IdempotencyDone", [keys.doneKey, keys.lockKey, keys.startKey], [String(this.idemDoneTimeout), keys.token], IdempotencyDone);
|
|
730
545
|
}
|
|
731
546
|
async idempotencyFree(keys) {
|
|
732
547
|
await this.runScript("IdempotencyFree", [keys.lockKey, keys.startKey], [keys.token], IdempotencyFree);
|
|
733
548
|
}
|
|
734
|
-
async
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
} catch (err) {
|
|
756
|
-
if (String(err?.message || "").includes("NOGROUP")) {
|
|
757
|
-
await this.createGroup();
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
return [];
|
|
761
|
-
}
|
|
762
|
-
async selectFresh() {
|
|
763
|
-
let entries = [];
|
|
764
|
-
try {
|
|
765
|
-
const res = await this.redis.xreadgroup(
|
|
766
|
-
"GROUP",
|
|
767
|
-
this.group,
|
|
768
|
-
this.consumer(),
|
|
769
|
-
"BLOCK",
|
|
770
|
-
Math.max(2, this.workerLoopIntervalMs | 0),
|
|
771
|
-
"COUNT",
|
|
772
|
-
this.workerBatchTasksCount,
|
|
773
|
-
"STREAMS",
|
|
774
|
-
this.stream,
|
|
775
|
-
">"
|
|
776
|
-
);
|
|
777
|
-
entries = res?.[0]?.[1] ?? [];
|
|
778
|
-
if (!(0, import_full_utils.isArrFilled)(entries)) {
|
|
779
|
-
return [];
|
|
780
|
-
}
|
|
781
|
-
} catch (err) {
|
|
782
|
-
if (String(err?.message || "").includes("NOGROUP")) {
|
|
783
|
-
await this.createGroup();
|
|
549
|
+
async success(queueName, task) {
|
|
550
|
+
if (this.logStatus) {
|
|
551
|
+
const statusKey = `${queueName}:${task.job}:`;
|
|
552
|
+
await this.incr(statusKey + "ok", this.logStatusTimeout);
|
|
553
|
+
await this.incr(statusKey + "ready", this.logStatusTimeout);
|
|
554
|
+
}
|
|
555
|
+
await this.onSuccess(queueName, task);
|
|
556
|
+
}
|
|
557
|
+
async error(err, queueName, task) {
|
|
558
|
+
const dlqKey = queueName + ":dlq";
|
|
559
|
+
const taskP = { ...task };
|
|
560
|
+
if (task.attempt >= this.retryCount) {
|
|
561
|
+
const statusKey = `${queueName}:${task.job}:`;
|
|
562
|
+
await this.addTasks(dlqKey, [{ ...taskP.payload }], {
|
|
563
|
+
createdAt: task.createdAt,
|
|
564
|
+
job: task.job,
|
|
565
|
+
attempt: task.attempt
|
|
566
|
+
});
|
|
567
|
+
if (this.logStatus) {
|
|
568
|
+
await this.incr(statusKey + "err", this.logStatusTimeout);
|
|
569
|
+
await this.incr(statusKey + "ready", this.logStatusTimeout);
|
|
784
570
|
}
|
|
571
|
+
} else {
|
|
572
|
+
await this.onRetry(err, queueName, task);
|
|
573
|
+
await this.addTasks(queueName, [{ ...taskP.payload }], {
|
|
574
|
+
createdAt: task.createdAt,
|
|
575
|
+
job: task.job,
|
|
576
|
+
attempt: task.attempt
|
|
577
|
+
});
|
|
785
578
|
}
|
|
786
|
-
|
|
579
|
+
await this.onError(err, queueName, task);
|
|
787
580
|
}
|
|
788
581
|
async waitAbortable(ttl) {
|
|
789
582
|
return new Promise((resolve) => {
|
|
@@ -815,8 +608,8 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
|
|
|
815
608
|
}
|
|
816
609
|
async sendHeartbeat(keys) {
|
|
817
610
|
try {
|
|
818
|
-
const r1 = await this.redis.pexpire(keys.lockKey, this.
|
|
819
|
-
const r2 = await this.redis.pexpire(keys.startKey, this.
|
|
611
|
+
const r1 = await this.redis.pexpire(keys.lockKey, this.idemLockTimeout);
|
|
612
|
+
const r2 = await this.redis.pexpire(keys.startKey, this.idemLockTimeout);
|
|
820
613
|
const ok1 = Number(r1 || 0) === 1;
|
|
821
614
|
const ok2 = Number(r2 || 0) === 1;
|
|
822
615
|
return ok1 || ok2;
|
|
@@ -825,10 +618,10 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
|
|
|
825
618
|
}
|
|
826
619
|
}
|
|
827
620
|
heartbeat(keys) {
|
|
828
|
-
if (this.
|
|
621
|
+
if (this.idemLockTimeout <= 0) {
|
|
829
622
|
return;
|
|
830
623
|
}
|
|
831
|
-
const workerHeartbeatTimeoutMs = Math.max(1e3, Math.floor(Math.max(5e3, this.
|
|
624
|
+
const workerHeartbeatTimeoutMs = Math.max(1e3, Math.floor(Math.max(5e3, this.idemLockTimeout | 0) / 4));
|
|
832
625
|
let timer;
|
|
833
626
|
let alive = true;
|
|
834
627
|
let hbFails = 0;
|
|
@@ -868,39 +661,190 @@ var PowerQueues = class extends import_power_redis.PowerRedis {
|
|
|
868
661
|
stop();
|
|
869
662
|
};
|
|
870
663
|
}
|
|
871
|
-
|
|
872
|
-
if (!
|
|
873
|
-
|
|
664
|
+
async runScript(name, keys, args, defaultCode) {
|
|
665
|
+
if (!this.scripts[name]) {
|
|
666
|
+
if (!(0, import_full_utils.isStrFilled)(defaultCode)) {
|
|
667
|
+
throw new Error(`Undefined script "${name}". Save it before executing.`);
|
|
668
|
+
}
|
|
669
|
+
this.saveScript(name, defaultCode);
|
|
670
|
+
}
|
|
671
|
+
if (!this.scripts[name].codeReady) {
|
|
672
|
+
this.scripts[name].codeReady = await this.loadScript(this.scripts[name].codeBody);
|
|
673
|
+
}
|
|
674
|
+
try {
|
|
675
|
+
return await this.redis.evalsha(this.scripts[name].codeReady, keys.length, ...keys, ...args);
|
|
676
|
+
} catch (err) {
|
|
677
|
+
if (String(err?.message || "").includes("NOSCRIPT")) {
|
|
678
|
+
this.scripts[name].codeReady = await this.loadScript(this.scripts[name].codeBody);
|
|
679
|
+
return await this.redis.evalsha(this.scripts[name].codeReady, keys.length, ...keys, ...args);
|
|
680
|
+
}
|
|
681
|
+
throw err;
|
|
874
682
|
}
|
|
875
|
-
return Array.from(raw || []).map((e) => {
|
|
876
|
-
const id = Buffer.isBuffer(e?.[0]) ? e[0].toString() : e?.[0];
|
|
877
|
-
const kvRaw = e?.[1] ?? [];
|
|
878
|
-
const kv = (0, import_full_utils.isArr)(kvRaw) ? kvRaw.map((x) => Buffer.isBuffer(x) ? x.toString() : x) : [];
|
|
879
|
-
return [id, kv];
|
|
880
|
-
}).filter(([id, kv]) => (0, import_full_utils.isStrFilled)(id) && (0, import_full_utils.isArr)(kv) && (kv.length & 1) === 0).map(([id, kv]) => {
|
|
881
|
-
const { idemKey = "", job, createdAt, payload } = this.values(kv);
|
|
882
|
-
return [id, this.payload(payload), createdAt, job, idemKey];
|
|
883
|
-
});
|
|
884
683
|
}
|
|
885
|
-
|
|
886
|
-
const
|
|
887
|
-
|
|
888
|
-
|
|
684
|
+
async loadScripts(full = false) {
|
|
685
|
+
const scripts = full ? [
|
|
686
|
+
["XAddBulk", XAddBulk],
|
|
687
|
+
["Approve", Approve],
|
|
688
|
+
["IdempotencyAllow", IdempotencyAllow],
|
|
689
|
+
["IdempotencyStart", IdempotencyStart],
|
|
690
|
+
["IdempotencyDone", IdempotencyDone],
|
|
691
|
+
["IdempotencyFree", IdempotencyFree],
|
|
692
|
+
["SelectStuck", SelectStuck]
|
|
693
|
+
] : [
|
|
694
|
+
["XAddBulk", XAddBulk]
|
|
695
|
+
];
|
|
696
|
+
for (const [name, code] of scripts) {
|
|
697
|
+
await this.loadScript(this.saveScript(name, code));
|
|
889
698
|
}
|
|
699
|
+
}
|
|
700
|
+
async loadScript(code) {
|
|
701
|
+
for (let i = 0; i < 3; i++) {
|
|
702
|
+
try {
|
|
703
|
+
return await this.redis.script("LOAD", code);
|
|
704
|
+
} catch (e) {
|
|
705
|
+
if (i === 2) {
|
|
706
|
+
throw e;
|
|
707
|
+
}
|
|
708
|
+
await new Promise((r) => setTimeout(r, 10 + Math.floor(Math.random() * 40)));
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
throw new Error("Load lua script failed.");
|
|
712
|
+
}
|
|
713
|
+
saveScript(name, codeBody) {
|
|
714
|
+
if (!(0, import_full_utils.isStrFilled)(codeBody)) {
|
|
715
|
+
throw new Error("Script body is empty.");
|
|
716
|
+
}
|
|
717
|
+
this.scripts[name] = { codeBody };
|
|
718
|
+
return codeBody;
|
|
719
|
+
}
|
|
720
|
+
async addTasks(queueName, data, opts = {}) {
|
|
721
|
+
if (!(0, import_full_utils.isArrFilled)(data)) {
|
|
722
|
+
throw new Error("Tasks is not filled.");
|
|
723
|
+
}
|
|
724
|
+
if (!(0, import_full_utils.isStrFilled)(queueName)) {
|
|
725
|
+
throw new Error("Queue name is required.");
|
|
726
|
+
}
|
|
727
|
+
const batches = this.buildBatches(data, opts);
|
|
728
|
+
const result = new Array(data.length);
|
|
729
|
+
const promises = [];
|
|
730
|
+
let cursor = 0;
|
|
731
|
+
for (const batch of batches) {
|
|
732
|
+
const start = cursor;
|
|
733
|
+
const end = start + batch.length;
|
|
734
|
+
cursor = end;
|
|
735
|
+
promises.push(async () => {
|
|
736
|
+
const payload = this.payloadBatch(batch, opts);
|
|
737
|
+
const partIds = await this.runScript("XAddBulk", [queueName], payload, XAddBulk);
|
|
738
|
+
for (let k = 0; k < partIds.length; k++) {
|
|
739
|
+
result[start + k] = partIds[k];
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
const runners = Array.from({ length: promises.length }, async () => {
|
|
744
|
+
while (promises.length) {
|
|
745
|
+
const promise = promises.shift();
|
|
746
|
+
if (promise) {
|
|
747
|
+
await promise();
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
if (opts.status) {
|
|
752
|
+
await this.redis.set(`${queueName}:${opts.job}:total`, data.length);
|
|
753
|
+
await this.redis.pexpire(`${queueName}:${opts.job}:total`, opts.statusTimeoutMs || 3e5);
|
|
754
|
+
}
|
|
755
|
+
await Promise.all(runners);
|
|
890
756
|
return result;
|
|
891
757
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
758
|
+
buildBatches(tasks, opts = {}) {
|
|
759
|
+
const batches = [];
|
|
760
|
+
let batch = [], realKeysLength = 0;
|
|
761
|
+
for (let task of tasks) {
|
|
762
|
+
const createdAt = opts?.createdAt || Date.now();
|
|
763
|
+
let entry = {};
|
|
764
|
+
if ((0, import_full_utils.isObj)(entry)) {
|
|
765
|
+
entry = {
|
|
766
|
+
payload: JSON.stringify(task),
|
|
767
|
+
attempt: Number(opts.attempt || 0),
|
|
768
|
+
job: opts.job ?? (0, import_uuid.v4)(),
|
|
769
|
+
idemKey: (0, import_uuid.v4)(),
|
|
770
|
+
createdAt
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
const reqKeysLength = this.keysLength(entry);
|
|
774
|
+
if (batch.length && (batch.length >= this.buildBatchCount || realKeysLength + reqKeysLength > this.buildBatchMaxCount)) {
|
|
775
|
+
batches.push(batch);
|
|
776
|
+
batch = [];
|
|
777
|
+
realKeysLength = 0;
|
|
778
|
+
}
|
|
779
|
+
batch.push(entry);
|
|
780
|
+
realKeysLength += reqKeysLength;
|
|
896
781
|
}
|
|
897
|
-
|
|
782
|
+
if (batch.length) {
|
|
783
|
+
batches.push(batch);
|
|
784
|
+
}
|
|
785
|
+
return batches;
|
|
898
786
|
}
|
|
899
|
-
|
|
900
|
-
|
|
787
|
+
keysLength(task) {
|
|
788
|
+
if ("payload" in task && (0, import_full_utils.isObj)(task.payload)) {
|
|
789
|
+
return 2 + Object.keys(task.payload).length * 2;
|
|
790
|
+
}
|
|
791
|
+
return 2 + Object.keys(task).length * 2;
|
|
901
792
|
}
|
|
902
|
-
|
|
903
|
-
|
|
793
|
+
payloadBatch(data, opts) {
|
|
794
|
+
const maxlen = Math.max(0, Math.floor(opts?.maxlen ?? 0));
|
|
795
|
+
const approx = opts?.exact ? 0 : opts?.approx !== false ? 1 : 0;
|
|
796
|
+
const exact = opts?.exact ? 1 : 0;
|
|
797
|
+
const nomkstream = opts?.nomkstream ? 1 : 0;
|
|
798
|
+
const trimLimit = Math.max(0, Math.floor(opts?.trimLimit ?? 0));
|
|
799
|
+
const minidWindowMs = Math.max(0, Math.floor(opts?.minidWindowMs ?? 0));
|
|
800
|
+
const minidExact = opts?.minidExact ? 1 : 0;
|
|
801
|
+
const argv = [
|
|
802
|
+
String(maxlen),
|
|
803
|
+
String(approx),
|
|
804
|
+
String(data.length),
|
|
805
|
+
String(exact),
|
|
806
|
+
String(nomkstream),
|
|
807
|
+
String(trimLimit),
|
|
808
|
+
String(minidWindowMs),
|
|
809
|
+
String(minidExact)
|
|
810
|
+
];
|
|
811
|
+
for (const item of data) {
|
|
812
|
+
const entry = item;
|
|
813
|
+
const id = entry.id ?? "*";
|
|
814
|
+
let flat = [];
|
|
815
|
+
if ("payload" in entry && (0, import_full_utils.isObjFilled)(entry)) {
|
|
816
|
+
for (const [k, v] of Object.entries(entry)) {
|
|
817
|
+
flat.push(k, v);
|
|
818
|
+
}
|
|
819
|
+
} else {
|
|
820
|
+
throw new Error('Task must have "payload" or "flat".');
|
|
821
|
+
}
|
|
822
|
+
const pairs = flat.length / 2;
|
|
823
|
+
if ((0, import_full_utils.isNumNZ)(pairs)) {
|
|
824
|
+
throw new Error('Task "flat" must contain at least one field/value pair.');
|
|
825
|
+
}
|
|
826
|
+
argv.push(String(id));
|
|
827
|
+
argv.push(String(pairs));
|
|
828
|
+
for (const token of flat) {
|
|
829
|
+
argv.push(!(0, import_full_utils.isExists)(token) ? "" : (0, import_full_utils.isStrFilled)(token) ? token : String(token));
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
return argv;
|
|
833
|
+
}
|
|
834
|
+
async beforeExecute(queueName, tasks) {
|
|
835
|
+
return tasks;
|
|
836
|
+
}
|
|
837
|
+
async onExecute(queueName, task) {
|
|
838
|
+
}
|
|
839
|
+
async onBatchSuccess(queueName, tasks) {
|
|
840
|
+
}
|
|
841
|
+
async onSuccess(queueName, task) {
|
|
842
|
+
}
|
|
843
|
+
async onError(err, queueName, task) {
|
|
844
|
+
}
|
|
845
|
+
async onBatchError(err, queueName, tasks) {
|
|
846
|
+
}
|
|
847
|
+
async onRetry(err, queueName, task) {
|
|
904
848
|
}
|
|
905
849
|
};
|
|
906
850
|
// Annotate the CommonJS export names for ESM import in node:
|