qdone 2.0.7-alpha → 2.0.9-alpha
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/commonjs/src/consumer.js +77 -36
- package/commonjs/src/enqueue.js +21 -21
- package/package.json +1 -1
- package/src/consumer.js +48 -16
- package/src/enqueue.js +19 -19
- package/npm-shrinkwrap.json +0 -16001
package/commonjs/src/consumer.js
CHANGED
|
@@ -83,19 +83,20 @@ var DoNotProcess = /** @class */ (function (_super) {
|
|
|
83
83
|
return DoNotProcess;
|
|
84
84
|
}(Error));
|
|
85
85
|
exports.DoNotProcess = DoNotProcess;
|
|
86
|
-
var debug = (0, debug_1.default)('qdone:
|
|
86
|
+
var debug = (0, debug_1.default)('qdone:consumer');
|
|
87
87
|
// Global flag for shutdown request
|
|
88
88
|
var shutdownRequested = false;
|
|
89
89
|
var shutdownCallbacks = [];
|
|
90
90
|
function requestShutdown() {
|
|
91
|
+
debug('requestShutdown');
|
|
91
92
|
shutdownRequested = true;
|
|
92
93
|
for (var _i = 0, shutdownCallbacks_1 = shutdownCallbacks; _i < shutdownCallbacks_1.length; _i++) {
|
|
93
94
|
var callback = shutdownCallbacks_1[_i];
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
catch (e) { }
|
|
95
|
+
debug('callback', callback);
|
|
96
|
+
callback();
|
|
97
|
+
// try { callback() } catch (e) { }
|
|
98
98
|
}
|
|
99
|
+
debug('requestShutdown done');
|
|
99
100
|
}
|
|
100
101
|
exports.requestShutdown = requestShutdown;
|
|
101
102
|
function processMessage(message, callback, qname, qrl, opt) {
|
|
@@ -167,7 +168,7 @@ function processMessage(message, callback, qname, qrl, opt) {
|
|
|
167
168
|
switch (_a.label) {
|
|
168
169
|
case 0:
|
|
169
170
|
debug('processMessage', message, qname, qrl);
|
|
170
|
-
payload = JSON.parse(message.Body);
|
|
171
|
+
payload = opt.json ? JSON.parse(message.Body) : message.Body;
|
|
171
172
|
if (opt.verbose) {
|
|
172
173
|
console.error(chalk_1.default.blue(' Processing payload:'), payload);
|
|
173
174
|
}
|
|
@@ -366,16 +367,19 @@ function processMessages(queues, callback, options) {
|
|
|
366
367
|
// Callback to help facilitate better UX at shutdown
|
|
367
368
|
function shutdownCallback() {
|
|
368
369
|
if (opt.verbose) {
|
|
369
|
-
debug({ activeLoops: activeLoops });
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
370
|
+
debug({ activeLoops: activeLoops, completedLoops: completedLoops });
|
|
371
|
+
if (activeLoops.length) {
|
|
372
|
+
console.error(chalk_1.default.blue('Waiting for work to finish on the following queues: '));
|
|
373
|
+
for (var _i = 0, activeLoops_2 = activeLoops; _i < activeLoops_2.length; _i++) {
|
|
374
|
+
var _a = activeLoops_2[_i], id = _a[0], _b = _a[1], qname = _b.qname, qrl = _b.qrl, promise = _b.promise;
|
|
375
|
+
console.error(' ' + qname + "job ".concat(id));
|
|
376
|
+
}
|
|
373
377
|
}
|
|
374
|
-
clearTimeout(delayTimeout)
|
|
378
|
+
// clearTimeout(delayTimeout)
|
|
375
379
|
}
|
|
376
380
|
}
|
|
377
381
|
// Listen to a queue until it is out of messages
|
|
378
|
-
function listenLoop(qname, qrl) {
|
|
382
|
+
function listenLoop(qname, qrl, loopId) {
|
|
379
383
|
return __awaiter(this, void 0, void 0, function () {
|
|
380
384
|
var _a, noJobs, jobsSucceeded, jobsFailed, err_3;
|
|
381
385
|
return __generator(this, function (_b) {
|
|
@@ -392,11 +396,14 @@ function processMessages(queues, callback, options) {
|
|
|
392
396
|
return [4 /*yield*/, pollSingleQueue(qname, qrl, callback, opt)];
|
|
393
397
|
case 1:
|
|
394
398
|
_a = _b.sent(), noJobs = _a.noJobs, jobsSucceeded = _a.jobsSucceeded, jobsFailed = _a.jobsFailed;
|
|
399
|
+
debug('pollSingleQueue return');
|
|
395
400
|
stats.noJobs += noJobs;
|
|
396
401
|
stats.jobsFailed += jobsFailed;
|
|
397
402
|
stats.jobsSucceeded += jobsSucceeded;
|
|
398
|
-
|
|
399
|
-
|
|
403
|
+
debug({ stats: stats, noJobs: noJobs });
|
|
404
|
+
// No work? Shutdown requested? Return to outer loop
|
|
405
|
+
debug({ noJobs: noJobs, shutdownRequested: shutdownRequested });
|
|
406
|
+
if (noJobs || shutdownRequested)
|
|
400
407
|
return [2 /*return*/];
|
|
401
408
|
// Otherwise keep going
|
|
402
409
|
return [2 /*return*/, listenLoop(qname, qrl)];
|
|
@@ -407,34 +414,38 @@ function processMessages(queues, callback, options) {
|
|
|
407
414
|
console.error(chalk_1.default.blue(' error : ') + err_3);
|
|
408
415
|
return [3 /*break*/, 4];
|
|
409
416
|
case 3:
|
|
410
|
-
|
|
417
|
+
completedLoops.set(loopId, activeLoops.get(loopId));
|
|
411
418
|
return [7 /*endfinally*/];
|
|
412
419
|
case 4: return [2 /*return*/];
|
|
413
420
|
}
|
|
414
421
|
});
|
|
415
422
|
});
|
|
416
423
|
}
|
|
417
|
-
var opt, stats, activeLoops, delayTimeout, delay, start, selectedPairs, _i, selectedPairs_1, _a, qname, qrl, msSoFar, msUntilNextResolve;
|
|
418
|
-
return __generator(this, function (
|
|
419
|
-
switch (
|
|
424
|
+
var opt, loopCounter, stats, maxActiveLoops, activeLoops, completedLoops, delayTimeout, delay, start, selectedPairs, _i, selectedPairs_1, _a, qname, qrl, loopId, msSoFar, msUntilNextResolve, _b, completedLoops_1, _c, id, _d, qname, qrl, promise, _e, activeLoops_1, _f, id, _g, qname, qrl, promise;
|
|
425
|
+
return __generator(this, function (_h) {
|
|
426
|
+
switch (_h.label) {
|
|
420
427
|
case 0:
|
|
421
428
|
opt = (0, defaults_js_1.getOptionsWithDefaults)(options);
|
|
422
429
|
debug('processMessages', { queues: queues, callback: callback, options: options, opt: opt });
|
|
430
|
+
loopCounter = 0;
|
|
423
431
|
stats = { noJobs: 0, jobsSucceeded: 0, jobsFailed: 0 };
|
|
424
|
-
|
|
432
|
+
maxActiveLoops = 10;
|
|
433
|
+
activeLoops = new Map();
|
|
434
|
+
completedLoops = new Map();
|
|
425
435
|
delay = function (ms) { return new Promise(function (resolve) {
|
|
426
436
|
delayTimeout = setTimeout(resolve, ms);
|
|
427
437
|
}); };
|
|
428
438
|
shutdownCallbacks.push(shutdownCallback);
|
|
429
|
-
|
|
439
|
+
_h.label = 1;
|
|
430
440
|
case 1:
|
|
431
|
-
if (!!shutdownRequested) return [3 /*break*/,
|
|
441
|
+
if (!!shutdownRequested) return [3 /*break*/, 9];
|
|
432
442
|
start = new Date();
|
|
433
443
|
return [4 /*yield*/, resolveQueues(queues, opt)];
|
|
434
444
|
case 2:
|
|
435
|
-
selectedPairs =
|
|
445
|
+
selectedPairs = _h.sent();
|
|
446
|
+
debug({ selectedPairs: selectedPairs });
|
|
436
447
|
if (shutdownRequested)
|
|
437
|
-
return [3 /*break*/,
|
|
448
|
+
return [3 /*break*/, 9];
|
|
438
449
|
// But only if we have queues to listen on
|
|
439
450
|
if (selectedPairs.length) {
|
|
440
451
|
// Randomize order
|
|
@@ -450,30 +461,60 @@ function processMessages(queues, callback, options) {
|
|
|
450
461
|
// Launch listen loop for each queue
|
|
451
462
|
for (_i = 0, selectedPairs_1 = selectedPairs; _i < selectedPairs_1.length; _i++) {
|
|
452
463
|
_a = selectedPairs_1[_i], qname = _a.qname, qrl = _a.qrl;
|
|
453
|
-
if
|
|
454
|
-
|
|
464
|
+
// Bail if we already have too many
|
|
465
|
+
if (activeLoops.size >= maxActiveLoops) {
|
|
466
|
+
if (opt.verbose)
|
|
467
|
+
console.error(chalk_1.default.yellow('Hit active worker limit of ') + maxActiveLoops);
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
loopId = loopCounter++;
|
|
471
|
+
activeLoops.set(loopId, { qname: qname, qrl: qrl, promise: listenLoop(qname, qrl, loopId) });
|
|
455
472
|
}
|
|
456
473
|
}
|
|
457
474
|
if (!!shutdownRequested) return [3 /*break*/, 4];
|
|
458
475
|
msSoFar = Math.max(0, new Date() - start);
|
|
459
|
-
msUntilNextResolve = Math.max(0, opt.waitTime
|
|
476
|
+
msUntilNextResolve = Math.max(0, /*opt.waitTime **/ 1000 - msSoFar);
|
|
460
477
|
debug({ msSoFar: msSoFar, msUntilNextResolve: msUntilNextResolve });
|
|
461
478
|
if (!msUntilNextResolve) return [3 /*break*/, 4];
|
|
462
479
|
if (opt.verbose)
|
|
463
480
|
console.error(chalk_1.default.blue('Will resolve queues again in ' + Math.round(msUntilNextResolve / 1000) + ' seconds'));
|
|
464
481
|
return [4 /*yield*/, delay(msUntilNextResolve)];
|
|
465
482
|
case 3:
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
case 4:
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
483
|
+
_h.sent();
|
|
484
|
+
_h.label = 4;
|
|
485
|
+
case 4:
|
|
486
|
+
_b = 0, completedLoops_1 = completedLoops;
|
|
487
|
+
_h.label = 5;
|
|
488
|
+
case 5:
|
|
489
|
+
if (!(_b < completedLoops_1.length)) return [3 /*break*/, 8];
|
|
490
|
+
_c = completedLoops_1[_b], id = _c[0], _d = _c[1], qname = _d.qname, qrl = _d.qrl, promise = _d.promise;
|
|
491
|
+
return [4 /*yield*/, promise]; // make sure the promise resolves
|
|
473
492
|
case 6:
|
|
474
|
-
//
|
|
475
|
-
|
|
476
|
-
|
|
493
|
+
_h.sent(); // make sure the promise resolves
|
|
494
|
+
debug('Cleaning up', { id: id, qname: qname, qrl: qrl, promise: promise });
|
|
495
|
+
activeLoops.delete(id);
|
|
496
|
+
_h.label = 7;
|
|
497
|
+
case 7:
|
|
498
|
+
_b++;
|
|
499
|
+
return [3 /*break*/, 5];
|
|
500
|
+
case 8: return [3 /*break*/, 1];
|
|
501
|
+
case 9:
|
|
502
|
+
debug('out here', { activeLoops: activeLoops });
|
|
503
|
+
_e = 0, activeLoops_1 = activeLoops;
|
|
504
|
+
_h.label = 10;
|
|
505
|
+
case 10:
|
|
506
|
+
if (!(_e < activeLoops_1.length)) return [3 /*break*/, 13];
|
|
507
|
+
_f = activeLoops_1[_e], id = _f[0], _g = _f[1], qname = _g.qname, qrl = _g.qrl, promise = _g.promise;
|
|
508
|
+
debug('Waiting on active loop', id);
|
|
509
|
+
return [4 /*yield*/, promise]; // make sure the promise resolves
|
|
510
|
+
case 11:
|
|
511
|
+
_h.sent(); // make sure the promise resolves
|
|
512
|
+
_h.label = 12;
|
|
513
|
+
case 12:
|
|
514
|
+
_e++;
|
|
515
|
+
return [3 /*break*/, 10];
|
|
516
|
+
case 13:
|
|
517
|
+
debug('after all');
|
|
477
518
|
return [2 /*return*/];
|
|
478
519
|
}
|
|
479
520
|
});
|
package/commonjs/src/enqueue.js
CHANGED
|
@@ -328,7 +328,7 @@ function sendMessageBatch(qrl, messages, opt) {
|
|
|
328
328
|
if (opt.fifo) {
|
|
329
329
|
params.Entries = params.Entries.map(function (message) { return Object.assign({
|
|
330
330
|
MessageGroupId: opt.groupIdPerMessage ? uuidFunction() : opt.groupId,
|
|
331
|
-
MessageDeduplicationId: uuidFunction()
|
|
331
|
+
MessageDeduplicationId: opt.deduplicationId || uuidFunction()
|
|
332
332
|
}, message); });
|
|
333
333
|
}
|
|
334
334
|
if (opt.delay) {
|
|
@@ -400,14 +400,13 @@ function sendMessageBatch(qrl, messages, opt) {
|
|
|
400
400
|
});
|
|
401
401
|
}
|
|
402
402
|
exports.sendMessageBatch = sendMessageBatch;
|
|
403
|
-
var messages = {};
|
|
404
403
|
var requestCount = 0;
|
|
405
404
|
//
|
|
406
405
|
// Flushes the internal message buffer for qrl.
|
|
407
406
|
// If the message is too large, batch is retried with half the messages.
|
|
408
407
|
// Returns number of messages flushed.
|
|
409
408
|
//
|
|
410
|
-
function flushMessages(qrl, opt) {
|
|
409
|
+
function flushMessages(qrl, opt, sendBuffer) {
|
|
411
410
|
return __awaiter(this, void 0, void 0, function () {
|
|
412
411
|
function whileNotEmpty() {
|
|
413
412
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -415,18 +414,18 @@ function flushMessages(qrl, opt) {
|
|
|
415
414
|
return __generator(this, function (_a) {
|
|
416
415
|
switch (_a.label) {
|
|
417
416
|
case 0:
|
|
418
|
-
if (!(
|
|
417
|
+
if (!(sendBuffer[qrl] && sendBuffer[qrl].length))
|
|
419
418
|
return [2 /*return*/, numFlushed
|
|
420
419
|
// Construct batch until full
|
|
421
420
|
];
|
|
422
421
|
batch = [];
|
|
423
|
-
nextSize = JSON.stringify(
|
|
422
|
+
nextSize = JSON.stringify(sendBuffer[qrl][0]).length;
|
|
424
423
|
totalSize = 0;
|
|
425
|
-
while ((totalSize + nextSize) < 262144 &&
|
|
426
|
-
batch.push(
|
|
424
|
+
while ((totalSize + nextSize) < 262144 && sendBuffer[qrl].length && batch.length < 10) {
|
|
425
|
+
batch.push(sendBuffer[qrl].shift());
|
|
427
426
|
totalSize += nextSize;
|
|
428
|
-
if (
|
|
429
|
-
nextSize = JSON.stringify(
|
|
427
|
+
if (sendBuffer[qrl].length)
|
|
428
|
+
nextSize = JSON.stringify(sendBuffer[qrl][0]).length;
|
|
430
429
|
else
|
|
431
430
|
nextSize = 0;
|
|
432
431
|
}
|
|
@@ -468,17 +467,16 @@ exports.flushMessages = flushMessages;
|
|
|
468
467
|
// Automaticaly flushes if queue has >= 10 messages.
|
|
469
468
|
// Returns number of messages flushed.
|
|
470
469
|
//
|
|
471
|
-
|
|
472
|
-
function addMessage(qrl, command, opt) {
|
|
470
|
+
function addMessage(qrl, command, messageIndex, opt, sendBuffer) {
|
|
473
471
|
return __awaiter(this, void 0, void 0, function () {
|
|
474
472
|
var message;
|
|
475
473
|
return __generator(this, function (_a) {
|
|
476
|
-
message = formatMessage(command, messageIndex
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
debug({ location: 'addMessage',
|
|
480
|
-
if (
|
|
481
|
-
return [2 /*return*/, flushMessages(qrl, opt)];
|
|
474
|
+
message = formatMessage(command, messageIndex);
|
|
475
|
+
sendBuffer[qrl] = sendBuffer[qrl] || [];
|
|
476
|
+
sendBuffer[qrl].push(message);
|
|
477
|
+
debug({ location: 'addMessage', sendBuffer: sendBuffer });
|
|
478
|
+
if (sendBuffer[qrl].length >= 10) {
|
|
479
|
+
return [2 /*return*/, flushMessages(qrl, opt, sendBuffer)];
|
|
482
480
|
}
|
|
483
481
|
return [2 /*return*/, 0];
|
|
484
482
|
});
|
|
@@ -512,7 +510,7 @@ exports.enqueue = enqueue;
|
|
|
512
510
|
//
|
|
513
511
|
function enqueueBatch(pairs, options) {
|
|
514
512
|
return __awaiter(this, void 0, void 0, function () {
|
|
515
|
-
var opt, normalizedPairs, uniqueQnames, createPromises, _i, uniqueQnames_1, qname, initialFlushTotal, _a, normalizedPairs_1, _b, qname, command, qrl, _c, extraFlushPromises, qrl, extraFlushCounts, extraFlushTotal, totalFlushed;
|
|
513
|
+
var opt, normalizedPairs, uniqueQnames, createPromises, _i, uniqueQnames_1, qname, sendBuffer, messageIndex, initialFlushTotal, _a, normalizedPairs_1, _b, qname, command, qrl, _c, extraFlushPromises, qrl, extraFlushCounts, extraFlushTotal, totalFlushed;
|
|
516
514
|
return __generator(this, function (_d) {
|
|
517
515
|
switch (_d.label) {
|
|
518
516
|
case 0:
|
|
@@ -540,6 +538,8 @@ function enqueueBatch(pairs, options) {
|
|
|
540
538
|
// After we've prefetched, all qrls are in cache
|
|
541
539
|
// so go back through the list of pairs and fire off messages
|
|
542
540
|
requestCount = 0;
|
|
541
|
+
sendBuffer = {};
|
|
542
|
+
messageIndex = 0;
|
|
543
543
|
initialFlushTotal = 0;
|
|
544
544
|
_a = 0, normalizedPairs_1 = normalizedPairs;
|
|
545
545
|
_d.label = 2;
|
|
@@ -550,7 +550,7 @@ function enqueueBatch(pairs, options) {
|
|
|
550
550
|
case 3:
|
|
551
551
|
qrl = _d.sent();
|
|
552
552
|
_c = initialFlushTotal;
|
|
553
|
-
return [4 /*yield*/, addMessage(qrl, command, opt)];
|
|
553
|
+
return [4 /*yield*/, addMessage(qrl, command, messageIndex++, opt, sendBuffer)];
|
|
554
554
|
case 4:
|
|
555
555
|
initialFlushTotal = _c + _d.sent();
|
|
556
556
|
_d.label = 5;
|
|
@@ -559,8 +559,8 @@ function enqueueBatch(pairs, options) {
|
|
|
559
559
|
return [3 /*break*/, 2];
|
|
560
560
|
case 6:
|
|
561
561
|
extraFlushPromises = [];
|
|
562
|
-
for (qrl in
|
|
563
|
-
extraFlushPromises.push(flushMessages(qrl, opt));
|
|
562
|
+
for (qrl in sendBuffer) {
|
|
563
|
+
extraFlushPromises.push(flushMessages(qrl, opt, sendBuffer));
|
|
564
564
|
}
|
|
565
565
|
return [4 /*yield*/, Promise.all(extraFlushPromises)];
|
|
566
566
|
case 7:
|
package/package.json
CHANGED
package/src/consumer.js
CHANGED
|
@@ -27,22 +27,26 @@ import { getSQSClient } from './sqs.js'
|
|
|
27
27
|
//
|
|
28
28
|
export class DoNotProcess extends Error {}
|
|
29
29
|
|
|
30
|
-
const debug = Debug('qdone:
|
|
30
|
+
const debug = Debug('qdone:consumer')
|
|
31
31
|
|
|
32
32
|
// Global flag for shutdown request
|
|
33
33
|
let shutdownRequested = false
|
|
34
34
|
const shutdownCallbacks = []
|
|
35
35
|
|
|
36
36
|
export function requestShutdown () {
|
|
37
|
+
debug('requestShutdown')
|
|
37
38
|
shutdownRequested = true
|
|
38
39
|
for (const callback of shutdownCallbacks) {
|
|
39
|
-
|
|
40
|
+
debug('callback', callback)
|
|
41
|
+
callback()
|
|
42
|
+
// try { callback() } catch (e) { }
|
|
40
43
|
}
|
|
44
|
+
debug('requestShutdown done')
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
export async function processMessage (message, callback, qname, qrl, opt) {
|
|
44
48
|
debug('processMessage', message, qname, qrl)
|
|
45
|
-
const payload = JSON.parse(message.Body)
|
|
49
|
+
const payload = opt.json ? JSON.parse(message.Body) : message.Body
|
|
46
50
|
if (opt.verbose) {
|
|
47
51
|
console.error(chalk.blue(' Processing payload:'), payload)
|
|
48
52
|
} else if (!opt.disableLog) {
|
|
@@ -248,8 +252,11 @@ export async function processMessages (queues, callback, options) {
|
|
|
248
252
|
const opt = getOptionsWithDefaults(options)
|
|
249
253
|
debug('processMessages', { queues, callback, options, opt })
|
|
250
254
|
|
|
255
|
+
let loopCounter = 0
|
|
251
256
|
const stats = { noJobs: 0, jobsSucceeded: 0, jobsFailed: 0 }
|
|
252
|
-
const
|
|
257
|
+
const maxActiveLoops = 10
|
|
258
|
+
const activeLoops = new Map()
|
|
259
|
+
const completedLoops = new Map()
|
|
253
260
|
|
|
254
261
|
// This delay function keeps a timeout reference around so it can be
|
|
255
262
|
// cancelled at shutdown
|
|
@@ -261,18 +268,20 @@ export async function processMessages (queues, callback, options) {
|
|
|
261
268
|
// Callback to help facilitate better UX at shutdown
|
|
262
269
|
function shutdownCallback () {
|
|
263
270
|
if (opt.verbose) {
|
|
264
|
-
debug({ activeLoops })
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
271
|
+
debug({ activeLoops, completedLoops })
|
|
272
|
+
if (activeLoops.length) {
|
|
273
|
+
console.error(chalk.blue('Waiting for work to finish on the following queues: '))
|
|
274
|
+
for (const [id, { qname, qrl, promise }] of activeLoops) {
|
|
275
|
+
console.error(' ' + qname + `job ${id}`)
|
|
276
|
+
}
|
|
268
277
|
}
|
|
269
|
-
clearTimeout(delayTimeout)
|
|
278
|
+
// clearTimeout(delayTimeout)
|
|
270
279
|
}
|
|
271
280
|
}
|
|
272
281
|
shutdownCallbacks.push(shutdownCallback)
|
|
273
282
|
|
|
274
283
|
// Listen to a queue until it is out of messages
|
|
275
|
-
async function listenLoop (qname, qrl) {
|
|
284
|
+
async function listenLoop (qname, qrl, loopId) {
|
|
276
285
|
try {
|
|
277
286
|
if (shutdownRequested) return
|
|
278
287
|
if (opt.verbose) {
|
|
@@ -284,12 +293,15 @@ export async function processMessages (queues, callback, options) {
|
|
|
284
293
|
}
|
|
285
294
|
// Aggregate the results
|
|
286
295
|
const { noJobs, jobsSucceeded, jobsFailed } = await pollSingleQueue(qname, qrl, callback, opt)
|
|
296
|
+
debug('pollSingleQueue return')
|
|
287
297
|
stats.noJobs += noJobs
|
|
288
298
|
stats.jobsFailed += jobsFailed
|
|
289
299
|
stats.jobsSucceeded += jobsSucceeded
|
|
300
|
+
debug({ stats, noJobs })
|
|
290
301
|
|
|
291
|
-
// No work?
|
|
292
|
-
|
|
302
|
+
// No work? Shutdown requested? Return to outer loop
|
|
303
|
+
debug({ noJobs, shutdownRequested })
|
|
304
|
+
if (noJobs || shutdownRequested) return
|
|
293
305
|
|
|
294
306
|
// Otherwise keep going
|
|
295
307
|
return listenLoop(qname, qrl)
|
|
@@ -298,7 +310,7 @@ export async function processMessages (queues, callback, options) {
|
|
|
298
310
|
console.error(chalk.red(' ERROR in listenLoop'))
|
|
299
311
|
console.error(chalk.blue(' error : ') + err)
|
|
300
312
|
} finally {
|
|
301
|
-
|
|
313
|
+
completedLoops.set(loopId, activeLoops.get(loopId))
|
|
302
314
|
}
|
|
303
315
|
}
|
|
304
316
|
|
|
@@ -306,6 +318,7 @@ export async function processMessages (queues, callback, options) {
|
|
|
306
318
|
while (!shutdownRequested) { // eslint-disable-line
|
|
307
319
|
const start = new Date()
|
|
308
320
|
const selectedPairs = await resolveQueues(queues, opt)
|
|
321
|
+
debug({ selectedPairs })
|
|
309
322
|
if (shutdownRequested) break
|
|
310
323
|
|
|
311
324
|
// But only if we have queues to listen on
|
|
@@ -323,24 +336,43 @@ export async function processMessages (queues, callback, options) {
|
|
|
323
336
|
|
|
324
337
|
// Launch listen loop for each queue
|
|
325
338
|
for (const { qname, qrl } of selectedPairs) {
|
|
326
|
-
if
|
|
339
|
+
// Bail if we already have too many
|
|
340
|
+
if (activeLoops.size >= maxActiveLoops) {
|
|
341
|
+
if (opt.verbose) console.error(chalk.yellow('Hit active worker limit of ') + maxActiveLoops)
|
|
342
|
+
break
|
|
343
|
+
}
|
|
344
|
+
const loopId = loopCounter++
|
|
345
|
+
activeLoops.set(loopId, { qname, qrl, promise: listenLoop(qname, qrl, loopId) })
|
|
327
346
|
}
|
|
328
347
|
}
|
|
348
|
+
|
|
329
349
|
// Wait until the next time we need to resolve
|
|
330
350
|
if (!shutdownRequested) {
|
|
331
351
|
const msSoFar = Math.max(0, new Date() - start)
|
|
332
|
-
const msUntilNextResolve = Math.max(0, opt.waitTime
|
|
352
|
+
const msUntilNextResolve = Math.max(0, /*opt.waitTime **/ 1000 - msSoFar)
|
|
333
353
|
debug({ msSoFar, msUntilNextResolve })
|
|
334
354
|
if (msUntilNextResolve) {
|
|
335
355
|
if (opt.verbose) console.error(chalk.blue('Will resolve queues again in ' + Math.round(msUntilNextResolve / 1000) + ' seconds'))
|
|
336
356
|
await delay(msUntilNextResolve)
|
|
337
357
|
}
|
|
338
358
|
}
|
|
359
|
+
|
|
360
|
+
// Cleanup completed loops
|
|
361
|
+
for (const [id, { qname, qrl, promise }] of completedLoops) {
|
|
362
|
+
await promise // make sure the promise resolves
|
|
363
|
+
debug('Cleaning up', { id, qname, qrl, promise })
|
|
364
|
+
activeLoops.delete(id)
|
|
365
|
+
}
|
|
339
366
|
}
|
|
367
|
+
debug('out here', { activeLoops })
|
|
340
368
|
|
|
341
369
|
// Wait on all work to finish
|
|
342
370
|
// shutdownCallback()
|
|
343
|
-
|
|
371
|
+
for (const [id, { qname, qrl, promise }] of activeLoops) {
|
|
372
|
+
debug('Waiting on active loop', id)
|
|
373
|
+
await promise // make sure the promise resolves
|
|
374
|
+
}
|
|
375
|
+
debug('after all')
|
|
344
376
|
}
|
|
345
377
|
|
|
346
378
|
debug('loaded')
|
package/src/enqueue.js
CHANGED
|
@@ -209,7 +209,7 @@ export async function sendMessageBatch (qrl, messages, opt) {
|
|
|
209
209
|
params.Entries = params.Entries.map(
|
|
210
210
|
message => Object.assign({
|
|
211
211
|
MessageGroupId: opt.groupIdPerMessage ? uuidFunction() : opt.groupId,
|
|
212
|
-
MessageDeduplicationId: uuidFunction()
|
|
212
|
+
MessageDeduplicationId: opt.deduplicationId || uuidFunction()
|
|
213
213
|
}, message)
|
|
214
214
|
)
|
|
215
215
|
}
|
|
@@ -267,7 +267,6 @@ export async function sendMessageBatch (qrl, messages, opt) {
|
|
|
267
267
|
return backoff.run(send, shouldRetry)
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
-
const messages = {}
|
|
271
270
|
let requestCount = 0
|
|
272
271
|
|
|
273
272
|
//
|
|
@@ -275,20 +274,20 @@ let requestCount = 0
|
|
|
275
274
|
// If the message is too large, batch is retried with half the messages.
|
|
276
275
|
// Returns number of messages flushed.
|
|
277
276
|
//
|
|
278
|
-
export async function flushMessages (qrl, opt) {
|
|
277
|
+
export async function flushMessages (qrl, opt, sendBuffer) {
|
|
279
278
|
debug('flushMessages', qrl)
|
|
280
279
|
// Flush until empty
|
|
281
280
|
let numFlushed = 0
|
|
282
281
|
async function whileNotEmpty () {
|
|
283
|
-
if (!(
|
|
282
|
+
if (!(sendBuffer[qrl] && sendBuffer[qrl].length)) return numFlushed
|
|
284
283
|
// Construct batch until full
|
|
285
284
|
const batch = []
|
|
286
|
-
let nextSize = JSON.stringify(
|
|
285
|
+
let nextSize = JSON.stringify(sendBuffer[qrl][0]).length
|
|
287
286
|
let totalSize = 0
|
|
288
|
-
while ((totalSize + nextSize) < 262144 &&
|
|
289
|
-
batch.push(
|
|
287
|
+
while ((totalSize + nextSize) < 262144 && sendBuffer[qrl].length && batch.length < 10) {
|
|
288
|
+
batch.push(sendBuffer[qrl].shift())
|
|
290
289
|
totalSize += nextSize
|
|
291
|
-
if (
|
|
290
|
+
if (sendBuffer[qrl].length) nextSize = JSON.stringify(sendBuffer[qrl][0]).length
|
|
292
291
|
else nextSize = 0
|
|
293
292
|
}
|
|
294
293
|
|
|
@@ -321,14 +320,13 @@ export async function flushMessages (qrl, opt) {
|
|
|
321
320
|
// Automaticaly flushes if queue has >= 10 messages.
|
|
322
321
|
// Returns number of messages flushed.
|
|
323
322
|
//
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
return flushMessages(qrl, opt)
|
|
323
|
+
export async function addMessage (qrl, command, messageIndex, opt, sendBuffer) {
|
|
324
|
+
const message = formatMessage(command, messageIndex)
|
|
325
|
+
sendBuffer[qrl] = sendBuffer[qrl] || []
|
|
326
|
+
sendBuffer[qrl].push(message)
|
|
327
|
+
debug({ location: 'addMessage', sendBuffer })
|
|
328
|
+
if (sendBuffer[qrl].length >= 10) {
|
|
329
|
+
return flushMessages(qrl, opt, sendBuffer)
|
|
332
330
|
}
|
|
333
331
|
return 0
|
|
334
332
|
}
|
|
@@ -370,16 +368,18 @@ export async function enqueueBatch (pairs, options) {
|
|
|
370
368
|
// After we've prefetched, all qrls are in cache
|
|
371
369
|
// so go back through the list of pairs and fire off messages
|
|
372
370
|
requestCount = 0
|
|
371
|
+
const sendBuffer = {}
|
|
372
|
+
let messageIndex = 0
|
|
373
373
|
let initialFlushTotal = 0
|
|
374
374
|
for (const { qname, command } of normalizedPairs) {
|
|
375
375
|
const qrl = await getOrCreateQueue(qname, opt)
|
|
376
|
-
initialFlushTotal += await addMessage(qrl, command, opt)
|
|
376
|
+
initialFlushTotal += await addMessage(qrl, command, messageIndex++, opt, sendBuffer)
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
// And flush any remaining messages
|
|
380
380
|
const extraFlushPromises = []
|
|
381
|
-
for (const qrl in
|
|
382
|
-
extraFlushPromises.push(flushMessages(qrl, opt))
|
|
381
|
+
for (const qrl in sendBuffer) {
|
|
382
|
+
extraFlushPromises.push(flushMessages(qrl, opt, sendBuffer))
|
|
383
383
|
}
|
|
384
384
|
const extraFlushCounts = await Promise.all(extraFlushPromises)
|
|
385
385
|
const extraFlushTotal = extraFlushCounts.reduce((a, b) => a + b, 0)
|