qdone 2.0.8-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/package.json +1 -1
- package/src/consumer.js +48 -16
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/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')
|