qdone 1.6.0 → 2.0.0-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.
Files changed (43) hide show
  1. package/README.md +9 -1
  2. package/commonjs/index.js +10 -0
  3. package/commonjs/package.json +3 -0
  4. package/commonjs/src/cache.js +142 -0
  5. package/commonjs/src/cloudWatch.js +148 -0
  6. package/commonjs/src/consumer.js +483 -0
  7. package/commonjs/src/defaults.js +107 -0
  8. package/commonjs/src/enqueue.js +498 -0
  9. package/commonjs/src/idleQueues.js +466 -0
  10. package/commonjs/src/qrlCache.js +250 -0
  11. package/commonjs/src/sqs.js +160 -0
  12. package/npm-shrinkwrap.json +17598 -264
  13. package/package.json +41 -29
  14. package/src/bin.js +3 -0
  15. package/src/cache.js +21 -25
  16. package/src/cli.js +269 -181
  17. package/src/cloudWatch.js +97 -0
  18. package/src/consumer.js +346 -0
  19. package/src/defaults.js +114 -0
  20. package/src/enqueue.js +239 -196
  21. package/src/idleQueues.js +242 -223
  22. package/src/monitor.js +53 -0
  23. package/src/qrlCache.js +110 -83
  24. package/src/sentry.js +30 -0
  25. package/src/sqs.js +73 -0
  26. package/src/worker.js +197 -202
  27. package/.DS_Store +0 -0
  28. package/.coveralls.yml +0 -2
  29. package/.travis.yml +0 -17
  30. package/CHANGELOG.md +0 -107
  31. package/dump.rdb +0 -0
  32. package/index.js +0 -6
  33. package/package-lock.json.old +0 -3939
  34. package/qdone +0 -2
  35. package/test/fixtures/test-child-kill-linux.sh +0 -9
  36. package/test/fixtures/test-fifo01-x24.batch +0 -24
  37. package/test/fixtures/test-too-big-1.batch +0 -10
  38. package/test/fixtures/test-unique01-x24.batch +0 -24
  39. package/test/fixtures/test-unique02-x24.batch +0 -24
  40. package/test/fixtures/test-unique24-x24.batch +0 -24
  41. package/test/fixtures/test-unique24-x240.batch +0 -240
  42. package/test/test.cache.js +0 -61
  43. package/test/test.cli.js +0 -1609
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ /**
3
+ * A cache for maintaining queue urls. Avoids having to call the GetQueueUrl
4
+ * api too often.
5
+ */
6
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
7
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
8
+ return new (P || (P = Promise))(function (resolve, reject) {
9
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
10
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
11
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
12
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
13
+ });
14
+ };
15
+ var __generator = (this && this.__generator) || function (thisArg, body) {
16
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
17
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
18
+ function verb(n) { return function (v) { return step([n, v]); }; }
19
+ function step(op) {
20
+ if (f) throw new TypeError("Generator is already executing.");
21
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
22
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
23
+ if (y = 0, t) op = [op[0] & 2, t.value];
24
+ switch (op[0]) {
25
+ case 0: case 1: t = op; break;
26
+ case 4: _.label++; return { value: op[1], done: false };
27
+ case 5: _.label++; y = op[1]; op = [0]; continue;
28
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
29
+ default:
30
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
31
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
32
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
33
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
34
+ if (t[2]) _.ops.pop();
35
+ _.trys.pop(); continue;
36
+ }
37
+ op = body.call(thisArg, _);
38
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
39
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
40
+ }
41
+ };
42
+ var __importDefault = (this && this.__importDefault) || function (mod) {
43
+ return (mod && mod.__esModule) ? mod : { "default": mod };
44
+ };
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.getQnameUrlPairs = exports.getMatchingQueues = exports.ingestQRLs = exports.qrlCacheInvalidate = exports.qrlCacheSet = exports.qrlCacheGet = exports.qrlCacheClear = exports.normalizeDLQName = exports.normalizeFailQueueName = exports.normalizeQueueName = exports.fifoSuffix = void 0;
47
+ var url_1 = require("url");
48
+ var path_1 = require("path");
49
+ var client_sqs_1 = require("@aws-sdk/client-sqs");
50
+ var sqs_js_1 = require("./sqs.js");
51
+ var debug_1 = __importDefault(require("debug"));
52
+ var debug = (0, debug_1.default)('qdone:qrlCache');
53
+ // The actual cache is shared across callers.
54
+ var qcache = new Map();
55
+ //
56
+ // Normalizes a queue name to end with .fifo if opt.fifo is set
57
+ //
58
+ exports.fifoSuffix = '.fifo';
59
+ function normalizeQueueName(qname, opt) {
60
+ var hasFifo = qname.endsWith(exports.fifoSuffix);
61
+ var needsFifo = opt.fifo && qname.slice(-1) !== '*';
62
+ var needsPrefix = !qname.startsWith(opt.prefix);
63
+ var base = hasFifo ? qname.slice(0, -exports.fifoSuffix.length) : qname;
64
+ return (needsPrefix ? opt.prefix : '') + base + (needsFifo ? exports.fifoSuffix : '');
65
+ }
66
+ exports.normalizeQueueName = normalizeQueueName;
67
+ //
68
+ // Normalizes fail queue name, appending both --fail-suffix and .fifo depending on opt
69
+ //
70
+ function normalizeFailQueueName(fqname, opt) {
71
+ var newopt = Object.assign({}, opt, { fifo: false });
72
+ var base = normalizeQueueName(fqname, newopt); // strip fifo
73
+ debug({ fqname: fqname, base: base, opt: opt });
74
+ var needsFail = !base.endsWith(opt.failSuffix);
75
+ return base + (needsFail ? opt.failSuffix : '') + (opt.fifo ? exports.fifoSuffix : '');
76
+ }
77
+ exports.normalizeFailQueueName = normalizeFailQueueName;
78
+ //
79
+ // Normalizes dlq queue name, appending both --dlq-suffix and .fifo depending on opt
80
+ //
81
+ function normalizeDLQName(dqname, opt) {
82
+ var newopt = Object.assign({}, opt, { fifo: false });
83
+ var base = normalizeQueueName(dqname, newopt); // strip fifo
84
+ var needsDead = !base.endsWith(opt.dlqSuffix);
85
+ return base + (needsDead ? opt.dlqSuffix : '') + (opt.fifo ? exports.fifoSuffix : '');
86
+ }
87
+ exports.normalizeDLQName = normalizeDLQName;
88
+ //
89
+ // Clear cache
90
+ //
91
+ function qrlCacheClear() {
92
+ qcache.clear();
93
+ }
94
+ exports.qrlCacheClear = qrlCacheClear;
95
+ //
96
+ // Get QRL (Queue URL)
97
+ // Returns a promise for the queue name
98
+ //
99
+ function qrlCacheGet(qname) {
100
+ return __awaiter(this, void 0, void 0, function () {
101
+ var client, input, cmd, result, qrl;
102
+ return __generator(this, function (_a) {
103
+ switch (_a.label) {
104
+ case 0:
105
+ debug('get', qname, qcache);
106
+ if (qcache.has(qname))
107
+ return [2 /*return*/, qcache.get(qname)];
108
+ client = (0, sqs_js_1.getSQSClient)();
109
+ input = { QueueName: qname };
110
+ cmd = new client_sqs_1.GetQueueUrlCommand(input);
111
+ return [4 /*yield*/, client.send(cmd)
112
+ // debug('result', result)
113
+ // if (!result) throw new Error(`No such queue ${qname}`)
114
+ ];
115
+ case 1:
116
+ result = _a.sent();
117
+ qrl = result.QueueUrl;
118
+ // debug('getQueueUrl returned', data)
119
+ qcache.set(qname, qrl);
120
+ // debug('qcache', Object.keys(qcache), 'get', qname, ' => ', qcache[qname])
121
+ return [2 /*return*/, qrl];
122
+ }
123
+ });
124
+ });
125
+ }
126
+ exports.qrlCacheGet = qrlCacheGet;
127
+ //
128
+ // Set QRL (Queue URL)
129
+ // Immediately updates the cache
130
+ //
131
+ function qrlCacheSet(qname, qrl) {
132
+ qcache.set(qname, qrl);
133
+ // debug('qcache', Object.keys(qcache), 'set', qname, ' => ', qcache[qname])
134
+ }
135
+ exports.qrlCacheSet = qrlCacheSet;
136
+ //
137
+ // Invalidate cache for given qname
138
+ //
139
+ function qrlCacheInvalidate(qname) {
140
+ // debug('qcache', Object.keys(qcache), 'delete', qname, ' (was ', qcache[qname], ')')
141
+ qcache.delete(qname);
142
+ }
143
+ exports.qrlCacheInvalidate = qrlCacheInvalidate;
144
+ //
145
+ // Ingets multiple QRLs
146
+ // Extracts queue names from an array of QRLs and immediately updates the cache.
147
+ //
148
+ function ingestQRLs(qrls) {
149
+ var pairs = [];
150
+ debug('ingestQRLs', qrls);
151
+ for (var _i = 0, qrls_1 = qrls; _i < qrls_1.length; _i++) {
152
+ var qrl = qrls_1[_i];
153
+ var qname = (0, path_1.basename)((new url_1.URL(qrl)).pathname);
154
+ qrlCacheSet(qname, qrl);
155
+ pairs.push({ qname: qname, qrl: qrl });
156
+ // debug('qcache', Object.keys(qcache), 'ingestQRLs', qname, ' => ', qcache[qname])
157
+ }
158
+ return pairs;
159
+ }
160
+ exports.ingestQRLs = ingestQRLs;
161
+ /**
162
+ * Returns qrls for queues matching the given prefix and regex.
163
+ */
164
+ function getMatchingQueues(prefix, nextToken) {
165
+ return __awaiter(this, void 0, void 0, function () {
166
+ var input, client, command, result, _a, qrls, keepGoing, _b, _c, _d;
167
+ var _e;
168
+ return __generator(this, function (_f) {
169
+ switch (_f.label) {
170
+ case 0:
171
+ debug('getMatchingQueues', prefix, nextToken);
172
+ input = { QueueNamePrefix: prefix, MaxResults: 1000 };
173
+ if (nextToken)
174
+ input.NextToken = nextToken;
175
+ client = (0, sqs_js_1.getSQSClient)();
176
+ command = new client_sqs_1.ListQueuesCommand(input);
177
+ return [4 /*yield*/, client.send(command)];
178
+ case 1:
179
+ result = _f.sent();
180
+ debug({ result: result });
181
+ _a = result || {}, qrls = _a.QueueUrls, keepGoing = _a.NextToken;
182
+ debug({ qrls: qrls, keepGoing: keepGoing });
183
+ if (!keepGoing) return [3 /*break*/, 3];
184
+ _c = (_b = (_e = (qrls || [])).push).apply;
185
+ _d = [_e];
186
+ return [4 /*yield*/, getMatchingQueues(prefix, keepGoing)];
187
+ case 2:
188
+ _c.apply(_b, _d.concat([_f.sent()]));
189
+ _f.label = 3;
190
+ case 3: return [2 /*return*/, qrls || []];
191
+ }
192
+ });
193
+ });
194
+ }
195
+ exports.getMatchingQueues = getMatchingQueues;
196
+ //
197
+ // Resolves into a flattened aray of {qname: ..., qrl: ...} objects.
198
+ //
199
+ function getQnameUrlPairs(qnames, opt) {
200
+ return __awaiter(this, void 0, void 0, function () {
201
+ var promises, results;
202
+ return __generator(this, function (_a) {
203
+ switch (_a.label) {
204
+ case 0:
205
+ promises = qnames.map(function getQueueUrlOrUrls(qname) {
206
+ return __awaiter(this, void 0, void 0, function () {
207
+ var prefix, queues, filteredQueues, err_1;
208
+ var _a;
209
+ return __generator(this, function (_b) {
210
+ switch (_b.label) {
211
+ case 0:
212
+ if (!(qname.slice(-1) === '*')) return [3 /*break*/, 2];
213
+ prefix = qname.slice(0, -1);
214
+ return [4 /*yield*/, getMatchingQueues(prefix)];
215
+ case 1:
216
+ queues = _b.sent();
217
+ debug('listQueues return', queues);
218
+ if (opt.fifo) {
219
+ filteredQueues = queues.filter(function (url) { return url.slice(-exports.fifoSuffix.length) === exports.fifoSuffix; });
220
+ return [2 /*return*/, ingestQRLs(filteredQueues)];
221
+ }
222
+ else {
223
+ return [2 /*return*/, ingestQRLs(queues)];
224
+ }
225
+ return [3 /*break*/, 5];
226
+ case 2:
227
+ _b.trys.push([2, 4, , 5]);
228
+ _a = { qname: qname };
229
+ return [4 /*yield*/, qrlCacheGet(qname)];
230
+ case 3: return [2 /*return*/, (_a.qrl = _b.sent(), _a)];
231
+ case 4:
232
+ err_1 = _b.sent();
233
+ if (!(err_1 instanceof client_sqs_1.QueueDoesNotExist))
234
+ throw err_1;
235
+ return [3 /*break*/, 5];
236
+ case 5: return [2 /*return*/];
237
+ }
238
+ });
239
+ });
240
+ });
241
+ return [4 /*yield*/, Promise.all(promises)];
242
+ case 1:
243
+ results = _a.sent();
244
+ return [2 /*return*/, ([].concat.apply([], results)).filter(function (r) { return r; })];
245
+ }
246
+ });
247
+ });
248
+ }
249
+ exports.getQnameUrlPairs = getQnameUrlPairs;
250
+ debug('loaded');
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ /**
3
+ * Functions that deal with SQS
4
+ */
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ var __generator = (this && this.__generator) || function (thisArg, body) {
15
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
16
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
17
+ function verb(n) { return function (v) { return step([n, v]); }; }
18
+ function step(op) {
19
+ if (f) throw new TypeError("Generator is already executing.");
20
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
21
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
22
+ if (y = 0, t) op = [op[0] & 2, t.value];
23
+ switch (op[0]) {
24
+ case 0: case 1: t = op; break;
25
+ case 4: _.label++; return { value: op[1], done: false };
26
+ case 5: _.label++; y = op[1]; op = [0]; continue;
27
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
28
+ default:
29
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
30
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
31
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
32
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
33
+ if (t[2]) _.ops.pop();
34
+ _.trys.pop(); continue;
35
+ }
36
+ op = body.call(thisArg, _);
37
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
38
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
39
+ }
40
+ };
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.getQueueAttributes = exports.getMatchingQueues = exports.setSQSClient = exports.getSQSClient = void 0;
46
+ var client_sqs_1 = require("@aws-sdk/client-sqs");
47
+ var path_1 = require("path");
48
+ var debug_1 = __importDefault(require("debug"));
49
+ var debug = (0, debug_1.default)('qdone:sqs');
50
+ /**
51
+ * Utility function to return an instantiated, shared SQSClient.
52
+ */
53
+ var client;
54
+ function getSQSClient() {
55
+ if (client)
56
+ return client;
57
+ client = new client_sqs_1.SQSClient();
58
+ return client;
59
+ }
60
+ exports.getSQSClient = getSQSClient;
61
+ /**
62
+ * Utility function to set the client explicitly, used in testing.
63
+ */
64
+ function setSQSClient(explicitClient) {
65
+ client = explicitClient;
66
+ }
67
+ exports.setSQSClient = setSQSClient;
68
+ /**
69
+ * Returns qrls for queues matching the given prefix and regex.
70
+ */
71
+ function getMatchingQueues(prefix, regex) {
72
+ return __awaiter(this, void 0, void 0, function () {
73
+ function processQueues(nextToken) {
74
+ return __awaiter(this, void 0, void 0, function () {
75
+ var command, result, qrls, nextToken2, _a, _b, _c;
76
+ return __generator(this, function (_d) {
77
+ switch (_d.label) {
78
+ case 0:
79
+ if (nextToken)
80
+ input.NextToken = nextToken;
81
+ command = new client_sqs_1.ListQueuesCommand(input);
82
+ return [4 /*yield*/, client.send(command)
83
+ // debug({ result })
84
+ ];
85
+ case 1:
86
+ result = _d.sent();
87
+ qrls = result.QueueUrls, nextToken2 = result.NextToken;
88
+ _b = (_a = (qrls || []).filter(function (q) { return regex.test(q); })).concat;
89
+ if (!nextToken2) return [3 /*break*/, 3];
90
+ return [4 /*yield*/, processQueues(nextToken2)];
91
+ case 2:
92
+ _c = _d.sent();
93
+ return [3 /*break*/, 4];
94
+ case 3:
95
+ _c = [];
96
+ _d.label = 4;
97
+ case 4:
98
+ // debug({ qrls, nextToken2 })
99
+ return [2 /*return*/, _b.apply(_a, [_c])];
100
+ }
101
+ });
102
+ });
103
+ }
104
+ var input, client;
105
+ return __generator(this, function (_a) {
106
+ input = { QueueNamePrefix: prefix, MaxResults: 1000 };
107
+ client = getSQSClient();
108
+ return [2 /*return*/, processQueues()];
109
+ });
110
+ });
111
+ }
112
+ exports.getMatchingQueues = getMatchingQueues;
113
+ /**
114
+ * Gets attributes on every queue in parallel.
115
+ */
116
+ function getQueueAttributes(qrls) {
117
+ return __awaiter(this, void 0, void 0, function () {
118
+ var promises, _loop_1, _i, qrls_1, qrl;
119
+ var _this = this;
120
+ return __generator(this, function (_a) {
121
+ promises = [];
122
+ _loop_1 = function (qrl) {
123
+ var input = {
124
+ QueueUrl: qrl,
125
+ AttributeNames: [
126
+ 'ApproximateNumberOfMessages',
127
+ 'ApproximateNumberOfMessagesNotVisible',
128
+ 'ApproximateNumberOfMessagesDelayed'
129
+ ]
130
+ };
131
+ var command = new client_sqs_1.GetQueueAttributesCommand(input);
132
+ // debug({ input, command })
133
+ promises.push((function () { return __awaiter(_this, void 0, void 0, function () {
134
+ var queue, result;
135
+ return __generator(this, function (_a) {
136
+ switch (_a.label) {
137
+ case 0:
138
+ queue = (0, path_1.basename)(qrl);
139
+ return [4 /*yield*/, client.send(command)
140
+ // debug({ queue, result })
141
+ ];
142
+ case 1:
143
+ result = _a.sent();
144
+ // debug({ queue, result })
145
+ return [2 /*return*/, { queue: queue, result: result }];
146
+ }
147
+ });
148
+ }); })());
149
+ };
150
+ // debug({ qrls })
151
+ for (_i = 0, qrls_1 = qrls; _i < qrls_1.length; _i++) {
152
+ qrl = qrls_1[_i];
153
+ _loop_1(qrl);
154
+ }
155
+ return [2 /*return*/, Promise.all(promises)];
156
+ });
157
+ });
158
+ }
159
+ exports.getQueueAttributes = getQueueAttributes;
160
+ debug('loaded');