qdone 2.0.12-alpha → 2.0.14-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 +91 -29
- package/commonjs/src/defaults.js +20 -1
- package/commonjs/src/idleQueues.js +2 -3
- package/commonjs/src/scheduler/jobExecutor.js +136 -100
- package/commonjs/src/scheduler/queueManager.js +116 -35
- package/commonjs/src/scheduler/systemMonitor.js +21 -37
- package/package.json +1 -1
- package/src/consumer.js +50 -22
- package/src/defaults.js +22 -1
- package/src/idleQueues.js +1 -1
- package/src/scheduler/jobExecutor.js +95 -51
- package/src/scheduler/queueManager.js +86 -23
- package/src/scheduler/systemMonitor.js +18 -32
|
@@ -47,7 +47,6 @@ var chalk_1 = __importDefault(require("chalk"));
|
|
|
47
47
|
var debug_1 = __importDefault(require("debug"));
|
|
48
48
|
var qrlCache_js_1 = require("../qrlCache.js");
|
|
49
49
|
var idleQueues_js_1 = require("../idleQueues.js");
|
|
50
|
-
var sqs_js_1 = require("../sqs.js");
|
|
51
50
|
var debug = (0, debug_1.default)('qdone:queueManager');
|
|
52
51
|
var QueueManager = /** @class */ (function () {
|
|
53
52
|
function QueueManager(opt, queues, resolveSeconds) {
|
|
@@ -56,72 +55,143 @@ var QueueManager = /** @class */ (function () {
|
|
|
56
55
|
this.queues = queues;
|
|
57
56
|
this.resolveSeconds = resolveSeconds;
|
|
58
57
|
this.selectedPairs = [];
|
|
58
|
+
this.icehouse = {};
|
|
59
59
|
this.resolveTimeout = undefined;
|
|
60
60
|
this.shutdownRequested = false;
|
|
61
|
-
this.resolveQueues();
|
|
61
|
+
this.resolvePromise = this.resolveQueues();
|
|
62
62
|
}
|
|
63
|
+
// Sends a queue to the icehouse, where it waits for a while before being
|
|
64
|
+
// checked again
|
|
65
|
+
QueueManager.prototype.updateIcehouse = function (qrl, emptyReceive) {
|
|
66
|
+
var foundEntry = !!this.icehouse[qrl];
|
|
67
|
+
var _a = this.icehouse[qrl] || {
|
|
68
|
+
lastCheck: new Date(),
|
|
69
|
+
secondsToWait: Math.round(20 + 10 * Math.random()),
|
|
70
|
+
numEmptyReceives: 0 + emptyReceive
|
|
71
|
+
}, lastCheck = _a.lastCheck, secondsToWait = _a.secondsToWait, numEmptyReceives = _a.numEmptyReceives;
|
|
72
|
+
if (emptyReceive) {
|
|
73
|
+
var now = new Date();
|
|
74
|
+
var secondsElapsed = lastCheck - now;
|
|
75
|
+
var minWait = 10;
|
|
76
|
+
var maxWait = 600;
|
|
77
|
+
var baseSeconds = Math.pow(numEmptyReceives, 2) * 20;
|
|
78
|
+
var jitterSeconds = Math.round((Math.random() - 0.5) * baseSeconds);
|
|
79
|
+
var newSecondsToWait = Math.max(minWait, Math.min(maxWait, baseSeconds + jitterSeconds));
|
|
80
|
+
var newEntry = { lastCheck: now, secondsToWait: newSecondsToWait, numEmptyReceives: numEmptyReceives + 1 };
|
|
81
|
+
this.icehouse[qrl] = newEntry;
|
|
82
|
+
if (this.opt.verbose) {
|
|
83
|
+
console.error(chalk_1.default.blue('Sending queue to icehouse'), qrl, chalk_1.default.blue('for'), newSecondsToWait, chalk_1.default.blue('seconds'));
|
|
84
|
+
}
|
|
85
|
+
debug({ foundEntry: foundEntry, newEntry: newEntry, lastCheck: lastCheck, secondsToWait: secondsToWait, now: now, secondsElapsed: secondsElapsed, maxWait: maxWait, minWait: minWait, baseSeconds: baseSeconds, jitterSeconds: jitterSeconds });
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
delete this.icehouse[qrl];
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
// Returns true if the queue should be kept in the icehouse
|
|
92
|
+
QueueManager.prototype.keepInIcehouse = function (qrl, now) {
|
|
93
|
+
if (this.icehouse[qrl]) {
|
|
94
|
+
var _a = this.icehouse[qrl], lastCheck = _a.lastCheck, secondsToWait = _a.secondsToWait;
|
|
95
|
+
var secondsElapsed = Math.round((now - lastCheck) / 1000);
|
|
96
|
+
debug({ icehouseCheck: { qrl: qrl, lastCheck: lastCheck, secondsToWait: secondsToWait, secondsElapsed: secondsElapsed } });
|
|
97
|
+
var letOut = secondsElapsed > secondsToWait;
|
|
98
|
+
if (letOut && this.opt.verbose) {
|
|
99
|
+
console.error(chalk_1.default.blue('Coming out of icehouse:'), qrl);
|
|
100
|
+
}
|
|
101
|
+
return !letOut;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
63
107
|
QueueManager.prototype.resolveQueues = function () {
|
|
64
108
|
return __awaiter(this, void 0, void 0, function () {
|
|
65
|
-
var qnames, pairs, activePairs;
|
|
109
|
+
var qnames, pairs, now, filteredPairs, activePairs;
|
|
66
110
|
var _this = this;
|
|
67
111
|
return __generator(this, function (_a) {
|
|
68
112
|
switch (_a.label) {
|
|
69
113
|
case 0:
|
|
114
|
+
clearTimeout(this.resolveTimeout);
|
|
70
115
|
if (this.shutdownRequested)
|
|
71
116
|
return [2 /*return*/];
|
|
72
|
-
// Start processing
|
|
73
|
-
if (this.opt.verbose)
|
|
74
|
-
console.error(chalk_1.default.blue('Resolving queues: ') + this.queues.join(' '));
|
|
75
117
|
qnames = this.queues.map(function (queue) { return (0, qrlCache_js_1.normalizeQueueName)(queue, _this.opt); });
|
|
76
118
|
return [4 /*yield*/, (0, qrlCache_js_1.getQnameUrlPairs)(qnames, this.opt)];
|
|
77
119
|
case 1:
|
|
78
120
|
pairs = _a.sent();
|
|
121
|
+
if (this.opt.verbose)
|
|
122
|
+
console.error(chalk_1.default.blue('Resolving queues:'));
|
|
79
123
|
if (this.shutdownRequested)
|
|
80
124
|
return [2 /*return*/];
|
|
125
|
+
now = new Date();
|
|
126
|
+
filteredPairs = pairs
|
|
127
|
+
// first failed
|
|
128
|
+
.filter(function (_a) {
|
|
129
|
+
var qname = _a.qname, qrl = _a.qrl;
|
|
130
|
+
var suf = _this.opt.failSuffix + (_this.opt.fifo ? '.fifo' : '');
|
|
131
|
+
var isFailQueue = qname.slice(-suf.length) === suf;
|
|
132
|
+
return _this.opt.includeFailed ? true : !isFailQueue;
|
|
133
|
+
})
|
|
134
|
+
// first fifo
|
|
135
|
+
.filter(function (_a) {
|
|
136
|
+
var qname = _a.qname, qrl = _a.qrl;
|
|
137
|
+
var isFifo = qname.endsWith('.fifo');
|
|
138
|
+
return _this.opt.fifo ? isFifo : !isFifo;
|
|
139
|
+
})
|
|
140
|
+
// then icehouse
|
|
141
|
+
.filter(function (_a) {
|
|
142
|
+
var qname = _a.qname, qrl = _a.qrl;
|
|
143
|
+
return !_this.keepInIcehouse(qrl, now);
|
|
144
|
+
});
|
|
81
145
|
activePairs = [];
|
|
82
146
|
if (!this.opt.activeOnly) return [3 /*break*/, 3];
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
147
|
+
if (this.opt.verbose) {
|
|
148
|
+
console.error(chalk_1.default.blue(' checking active only'));
|
|
149
|
+
}
|
|
150
|
+
return [4 /*yield*/, Promise.all(filteredPairs.map(function (_a) {
|
|
151
|
+
var qname = _a.qname, qrl = _a.qrl;
|
|
152
|
+
return __awaiter(_this, void 0, void 0, function () {
|
|
153
|
+
var idle;
|
|
154
|
+
return __generator(this, function (_b) {
|
|
155
|
+
switch (_b.label) {
|
|
156
|
+
case 0: return [4 /*yield*/, (0, idleQueues_js_1.cheapIdleCheck)(qname, qrl, this.opt)];
|
|
157
|
+
case 1:
|
|
158
|
+
idle = (_b.sent()).result.idle;
|
|
159
|
+
debug({ idle: idle, qname: qname });
|
|
160
|
+
if (!idle)
|
|
161
|
+
activePairs.push({ qname: qname, qrl: qrl });
|
|
162
|
+
return [2 /*return*/];
|
|
163
|
+
}
|
|
164
|
+
});
|
|
95
165
|
});
|
|
96
|
-
})
|
|
166
|
+
}))];
|
|
97
167
|
case 2:
|
|
98
168
|
_a.sent();
|
|
99
169
|
_a.label = 3;
|
|
100
170
|
case 3:
|
|
101
171
|
if (this.shutdownRequested)
|
|
102
172
|
return [2 /*return*/];
|
|
103
|
-
// Finished resolving
|
|
104
|
-
if (this.opt.verbose) {
|
|
105
|
-
console.error(chalk_1.default.blue(' done'));
|
|
106
|
-
console.error();
|
|
107
|
-
}
|
|
108
173
|
// Figure out which queues we want to listen on, choosing between active and
|
|
109
174
|
// all, filtering out failed queues if the user wants that
|
|
110
|
-
this.selectedPairs = (this.opt.activeOnly ? activePairs :
|
|
111
|
-
.filter(function (_a) {
|
|
112
|
-
var qname = _a.qname;
|
|
113
|
-
var suf = _this.opt.failSuffix + (_this.opt.fifo ? '.fifo' : '');
|
|
114
|
-
var isFailQueue = qname.slice(-suf.length) === suf;
|
|
115
|
-
var shouldInclude = _this.opt.includeFailed ? true : !isFailQueue;
|
|
116
|
-
return shouldInclude;
|
|
117
|
-
});
|
|
175
|
+
this.selectedPairs = (this.opt.activeOnly ? activePairs : filteredPairs);
|
|
118
176
|
// Randomize order
|
|
119
177
|
this.selectedPairs.sort(function () { return 0.5 - Math.random(); });
|
|
178
|
+
if (this.opt.verbose)
|
|
179
|
+
console.error(chalk_1.default.blue(' selected:\n ') + this.selectedPairs.map(function (_a) {
|
|
180
|
+
var qname = _a.qname;
|
|
181
|
+
return qname;
|
|
182
|
+
}).join('\n '));
|
|
120
183
|
debug('selectedPairs', this.selectedPairs);
|
|
184
|
+
// Finished resolving
|
|
185
|
+
if (this.opt.verbose) {
|
|
186
|
+
console.error(chalk_1.default.blue(' done'));
|
|
187
|
+
console.error();
|
|
188
|
+
}
|
|
121
189
|
if (this.opt.verbose) {
|
|
122
190
|
console.error(chalk_1.default.blue('Will resolve queues again in ' + this.resolveSeconds + ' seconds'));
|
|
123
191
|
}
|
|
124
|
-
this.resolveTimeout = setTimeout(function () {
|
|
192
|
+
this.resolveTimeout = setTimeout(function () {
|
|
193
|
+
_this.resolvePromise = _this.resolveQueues();
|
|
194
|
+
}, this.resolveSeconds * 1000);
|
|
125
195
|
return [2 /*return*/];
|
|
126
196
|
}
|
|
127
197
|
});
|
|
@@ -137,8 +207,19 @@ var QueueManager = /** @class */ (function () {
|
|
|
137
207
|
return this.selectedPairs;
|
|
138
208
|
};
|
|
139
209
|
QueueManager.prototype.shutdown = function () {
|
|
140
|
-
|
|
141
|
-
|
|
210
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
211
|
+
return __generator(this, function (_a) {
|
|
212
|
+
switch (_a.label) {
|
|
213
|
+
case 0:
|
|
214
|
+
this.shutdownRequested = true;
|
|
215
|
+
clearTimeout(this.resolveTimeout);
|
|
216
|
+
return [4 /*yield*/, this.resolvePromise];
|
|
217
|
+
case 1:
|
|
218
|
+
_a.sent();
|
|
219
|
+
return [2 /*return*/];
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
});
|
|
142
223
|
};
|
|
143
224
|
return QueueManager;
|
|
144
225
|
}());
|
|
@@ -6,59 +6,43 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.SystemMonitor = void 0;
|
|
8
8
|
var SystemMonitor = /** @class */ (function () {
|
|
9
|
-
function SystemMonitor(
|
|
10
|
-
if (
|
|
11
|
-
|
|
12
|
-
this.opt = opt;
|
|
13
|
-
this.smoothingFactor = smoothingFactor;
|
|
9
|
+
function SystemMonitor(reportCallback, reportSeconds) {
|
|
10
|
+
if (reportSeconds === void 0) { reportSeconds = 1; }
|
|
11
|
+
this.reportCallback = reportCallback || console.log;
|
|
14
12
|
this.reportSeconds = reportSeconds;
|
|
15
|
-
this.measurements =
|
|
16
|
-
|
|
17
|
-
setImmediate: []
|
|
18
|
-
};
|
|
19
|
-
this.timeouts = {
|
|
20
|
-
setTimeout: undefined,
|
|
21
|
-
setImmediate: undefined,
|
|
22
|
-
reportLatency: undefined
|
|
23
|
-
};
|
|
24
|
-
this.measureLatencySetTimeout();
|
|
13
|
+
this.measurements = [];
|
|
14
|
+
this.measure();
|
|
25
15
|
this.reportLatency();
|
|
26
16
|
}
|
|
27
|
-
SystemMonitor.prototype.
|
|
17
|
+
SystemMonitor.prototype.measure = function () {
|
|
28
18
|
var _this = this;
|
|
19
|
+
clearTimeout(this.measureTimeout);
|
|
29
20
|
var start = new Date();
|
|
30
|
-
this.
|
|
21
|
+
this.measureTimeout = setTimeout(function () {
|
|
31
22
|
var latency = new Date() - start;
|
|
32
|
-
_this.measurements.
|
|
33
|
-
if (_this.measurements.
|
|
34
|
-
_this.measurements.
|
|
35
|
-
_this.
|
|
23
|
+
_this.measurements.push(latency);
|
|
24
|
+
if (_this.measurements.length > 1000)
|
|
25
|
+
_this.measurements.shift();
|
|
26
|
+
_this.measure();
|
|
36
27
|
});
|
|
37
28
|
};
|
|
38
29
|
SystemMonitor.prototype.getLatency = function () {
|
|
39
|
-
|
|
40
|
-
for (var k in this.measurements) {
|
|
41
|
-
var values = this.measurements[k];
|
|
42
|
-
results[k] = values.length ? values.reduce(function (a, b) { return a + b; }, 0) / values.length : 0;
|
|
43
|
-
}
|
|
44
|
-
return results;
|
|
30
|
+
return this.measurements.length ? this.measurements.reduce(function (a, b) { return a + b; }, 0) / this.measurements.length : 0;
|
|
45
31
|
};
|
|
46
32
|
SystemMonitor.prototype.reportLatency = function () {
|
|
47
33
|
var _this = this;
|
|
48
|
-
this.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
34
|
+
clearTimeout(this.reportTimeout);
|
|
35
|
+
this.reportTimeout = setTimeout(function () {
|
|
36
|
+
var latency = _this.getLatency();
|
|
37
|
+
// console.log({ latency })
|
|
38
|
+
if (_this.reportCallback)
|
|
39
|
+
_this.reportCallback(latency);
|
|
55
40
|
_this.reportLatency();
|
|
56
41
|
}, this.reportSeconds * 1000);
|
|
57
42
|
};
|
|
58
43
|
SystemMonitor.prototype.shutdown = function () {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
clearTimeout(this.timeouts[k]);
|
|
44
|
+
clearTimeout(this.measureTimeout);
|
|
45
|
+
clearTimeout(this.reportTimeout);
|
|
62
46
|
};
|
|
63
47
|
return SystemMonitor;
|
|
64
48
|
}());
|
package/package.json
CHANGED
package/src/consumer.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Consumer implementation.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { ReceiveMessageCommand } from '@aws-sdk/client-sqs'
|
|
5
|
+
import { ReceiveMessageCommand, QueueDoesNotExist } from '@aws-sdk/client-sqs'
|
|
6
6
|
import chalk from 'chalk'
|
|
7
7
|
import Debug from 'debug'
|
|
8
8
|
|
|
@@ -18,12 +18,12 @@ const debug = Debug('qdone:consumer')
|
|
|
18
18
|
let shutdownRequested = false
|
|
19
19
|
const shutdownCallbacks = []
|
|
20
20
|
|
|
21
|
-
export function requestShutdown () {
|
|
21
|
+
export async function requestShutdown () {
|
|
22
22
|
debug('requestShutdown')
|
|
23
23
|
shutdownRequested = true
|
|
24
24
|
for (const callback of shutdownCallbacks) {
|
|
25
25
|
debug('callback', callback)
|
|
26
|
-
callback()
|
|
26
|
+
await callback()
|
|
27
27
|
// try { callback() } catch (e) { }
|
|
28
28
|
}
|
|
29
29
|
debug('requestShutdown done')
|
|
@@ -35,7 +35,7 @@ export async function getMessages (qrl, opt, maxMessages) {
|
|
|
35
35
|
MaxNumberOfMessages: maxMessages,
|
|
36
36
|
MessageAttributeNames: ['All'],
|
|
37
37
|
QueueUrl: qrl,
|
|
38
|
-
VisibilityTimeout:
|
|
38
|
+
VisibilityTimeout: 60,
|
|
39
39
|
WaitTimeSeconds: opt.waitTime
|
|
40
40
|
}
|
|
41
41
|
const response = await getSQSClient().send(new ReceiveMessageCommand(params))
|
|
@@ -47,20 +47,21 @@ export async function getMessages (qrl, opt, maxMessages) {
|
|
|
47
47
|
// Consumer
|
|
48
48
|
//
|
|
49
49
|
export async function processMessages (queues, callback, options) {
|
|
50
|
+
debug({ options })
|
|
50
51
|
const opt = getOptionsWithDefaults(options)
|
|
51
|
-
debug('processMessages', { queues, callback, options, opt })
|
|
52
|
+
debug('processMessages', { queues, callback, options, opt, argv: process.argv })
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
let lastLatency = 10
|
|
55
|
+
const systemMonitor = new SystemMonitor(latency => {
|
|
56
|
+
const percentDifference = 100 * Math.abs(lastLatency - latency) / lastLatency
|
|
57
|
+
if (percentDifference > 10 && opt.verbose) {
|
|
58
|
+
console.error(chalk.blue('Latency:', Math.round(latency), 'ms'))
|
|
59
|
+
}
|
|
60
|
+
lastLatency = latency
|
|
61
|
+
})
|
|
54
62
|
const jobExecutor = new JobExecutor(opt)
|
|
55
63
|
const queueManager = new QueueManager(opt, queues)
|
|
56
|
-
|
|
57
|
-
debug({ systemMonitor, jobExecutor, queueManager })
|
|
58
|
-
|
|
59
|
-
shutdownCallbacks.push(() => {
|
|
60
|
-
systemMonitor.shutdown()
|
|
61
|
-
queueManager.shutdown()
|
|
62
|
-
jobExecutor.shutdown()
|
|
63
|
-
})
|
|
64
|
+
// debug({ systemMonitor, jobExecutor, queueManager })
|
|
64
65
|
|
|
65
66
|
// This delay function keeps a timeout reference around so it can be
|
|
66
67
|
// cancelled at shutdown
|
|
@@ -69,28 +70,55 @@ export async function processMessages (queues, callback, options) {
|
|
|
69
70
|
delayTimeout = setTimeout(resolve, ms)
|
|
70
71
|
})
|
|
71
72
|
|
|
73
|
+
shutdownCallbacks.push(async () => {
|
|
74
|
+
clearTimeout(delayTimeout)
|
|
75
|
+
await queueManager.shutdown()
|
|
76
|
+
debug({ queueManager: 'done' })
|
|
77
|
+
await jobExecutor.shutdown()
|
|
78
|
+
debug({ jobExecutor: 'done' })
|
|
79
|
+
await systemMonitor.shutdown()
|
|
80
|
+
debug({ systemMonitor: 'done' })
|
|
81
|
+
})
|
|
82
|
+
|
|
72
83
|
// Keep track of how many messages could be returned from each queue
|
|
73
84
|
const activeQrls = new Set()
|
|
74
85
|
let maxReturnCount = 0
|
|
75
86
|
const listen = async (qname, qrl, maxMessages) => {
|
|
76
87
|
activeQrls.add(qrl)
|
|
77
88
|
maxReturnCount += maxMessages
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
89
|
+
try {
|
|
90
|
+
const messages = await getMessages(qrl, opt, maxMessages)
|
|
91
|
+
if (messages.length) {
|
|
92
|
+
for (const message of messages) {
|
|
93
|
+
jobExecutor.executeJob(message, callback, qname, qrl)
|
|
94
|
+
}
|
|
95
|
+
queueManager.updateIcehouse(qrl, false)
|
|
96
|
+
} else {
|
|
97
|
+
// If we didn't get any, update the icehouse so we can back off
|
|
98
|
+
queueManager.updateIcehouse(qrl, true)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Max job accounting
|
|
102
|
+
maxReturnCount -= maxMessages
|
|
103
|
+
activeQrls.delete(qrl)
|
|
104
|
+
} catch (e) {
|
|
105
|
+
// If the queue has been cleaned up, we should back off anyway
|
|
106
|
+
if (e instanceof QueueDoesNotExist) {
|
|
107
|
+
queueManager.updateIcehouse(qrl, true)
|
|
108
|
+
} else {
|
|
109
|
+
throw e
|
|
110
|
+
}
|
|
81
111
|
}
|
|
82
|
-
maxReturnCount -= maxMessages
|
|
83
|
-
activeQrls.delete(qrl)
|
|
84
112
|
}
|
|
85
113
|
|
|
86
114
|
while (!shutdownRequested) { // eslint-disable-line
|
|
87
115
|
// Figure out how we are running
|
|
88
|
-
const allowedJobs =
|
|
116
|
+
const allowedJobs = opt.maxConcurrentJobs - jobExecutor.activeJobCount() - maxReturnCount
|
|
89
117
|
const maxLatency = 100
|
|
90
118
|
const latency = systemMonitor.getLatency().setTimeout
|
|
91
119
|
const latencyFactor = 1 - Math.abs(Math.min(latency / maxLatency, 1)) // 0 if latency is at max, 1 if latency 0
|
|
92
120
|
const targetJobs = Math.round(allowedJobs * latencyFactor)
|
|
93
|
-
debug({ allowedJobs, maxLatency, latency, latencyFactor, targetJobs, activeQrls })
|
|
121
|
+
// debug({ allowedJobs, maxLatency, latency, latencyFactor, targetJobs, activeQrls })
|
|
94
122
|
|
|
95
123
|
let jobsLeft = targetJobs
|
|
96
124
|
for (const { qname, qrl } of queueManager.getPairs()) {
|
|
@@ -101,7 +129,7 @@ export async function processMessages (queues, callback, options) {
|
|
|
101
129
|
if (opt.verbose) {
|
|
102
130
|
console.error(chalk.blue('Listening on: '), qname)
|
|
103
131
|
}
|
|
104
|
-
debug({ listenedTo: { qname, maxMessages, jobsLeft } })
|
|
132
|
+
// debug({ listenedTo: { qname, maxMessages, jobsLeft } })
|
|
105
133
|
}
|
|
106
134
|
await delay(1000)
|
|
107
135
|
}
|
package/src/defaults.js
CHANGED
|
@@ -36,6 +36,7 @@ export const defaults = Object.freeze({
|
|
|
36
36
|
killAfter: 30,
|
|
37
37
|
archive: false,
|
|
38
38
|
activeOnly: false,
|
|
39
|
+
maxConcurrentJobs: 100,
|
|
39
40
|
|
|
40
41
|
// Idle Queues
|
|
41
42
|
idleFor: 60,
|
|
@@ -43,6 +44,12 @@ export const defaults = Object.freeze({
|
|
|
43
44
|
unpair: false
|
|
44
45
|
})
|
|
45
46
|
|
|
47
|
+
function validateInteger (opt, name) {
|
|
48
|
+
const parsed = parseInt(opt[name], 10)
|
|
49
|
+
if (isNaN(parsed)) throw new Error(`${name} needs to be an integer.`)
|
|
50
|
+
return parsed
|
|
51
|
+
}
|
|
52
|
+
|
|
46
53
|
/**
|
|
47
54
|
* This function should be called by each exposed API entry point on the
|
|
48
55
|
* options passed in from the caller. It supports options named in camelCase
|
|
@@ -93,15 +100,29 @@ export function getOptionsWithDefaults (options) {
|
|
|
93
100
|
archive: options.archive || defaults.archive,
|
|
94
101
|
activeOnly: options.activeOnly || options['active-only'] || defaults.activeOnly,
|
|
95
102
|
includeFailed: options.includeFailed || options['include-failed'] || defaults.includeFailed,
|
|
103
|
+
maxConcurrentJobs: options.maxConcurrentJobs || defaults.maxConcurrentJobs,
|
|
96
104
|
|
|
97
105
|
// Idle Queues
|
|
98
106
|
idleFor: options.idleFor || options['idle-for'] || defaults.idleFor,
|
|
99
107
|
delete: options.delete || defaults.delete,
|
|
100
108
|
unpair: options.delete || defaults.unpair
|
|
101
109
|
}
|
|
110
|
+
|
|
111
|
+
// Setting this env here means we don't have to in AWS SDK constructors
|
|
102
112
|
process.env.AWS_REGION = opt.region
|
|
103
113
|
|
|
104
|
-
//
|
|
114
|
+
// Validation
|
|
115
|
+
opt.cacheTtlSeconds = validateInteger(opt, 'cacheTtlSeconds')
|
|
116
|
+
opt.messageRetentionPeriod = validateInteger(opt, 'messageRetentionPeriod')
|
|
117
|
+
opt.delay = validateInteger(opt, 'delay')
|
|
118
|
+
opt.sendRetries = validateInteger(opt, 'sendRetries')
|
|
119
|
+
opt.failDelay = validateInteger(opt, 'failDelay')
|
|
120
|
+
opt.dlqAfter = validateInteger(opt, 'dlqAfter')
|
|
121
|
+
opt.waitTime = validateInteger(opt, 'waitTime')
|
|
122
|
+
opt.killAfter = validateInteger(opt, 'killAfter')
|
|
123
|
+
opt.maxConcurrentJobs = validateInteger(opt, 'maxConcurrentJobs')
|
|
124
|
+
opt.idleFor = validateInteger(opt, 'idleFor')
|
|
125
|
+
|
|
105
126
|
return opt
|
|
106
127
|
}
|
|
107
128
|
|
package/src/idleQueues.js
CHANGED
|
@@ -40,7 +40,7 @@ export async function _cheapIdleCheck (qname, qrl, opt) {
|
|
|
40
40
|
const client = getSQSClient()
|
|
41
41
|
const cmd = new GetQueueAttributesCommand({ AttributeNames: attributeNames, QueueUrl: qrl })
|
|
42
42
|
const data = await client.send(cmd)
|
|
43
|
-
|
|
43
|
+
debug('data', data)
|
|
44
44
|
const result = data.Attributes
|
|
45
45
|
result.queue = qname.slice(opt.prefix.length)
|
|
46
46
|
// We are idle if all the messages attributes are zero
|