qdone 2.0.29-alpha → 2.0.30-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.
@@ -1,246 +1,153 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- 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;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
39
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
40
4
  };
41
5
  Object.defineProperty(exports, "__esModule", { value: true });
42
6
  exports.enqueueBatch = exports.enqueue = exports.addMessage = exports.flushMessages = exports.sendMessageBatch = exports.sendMessage = exports.formatMessage = exports.getQueueAttributes = exports.getOrCreateQueue = exports.getOrCreateFailQueue = exports.getOrCreateDLQ = void 0;
43
- var node_1 = require("@sentry/node");
44
- var uuid_1 = require("uuid");
45
- var chalk_1 = __importDefault(require("chalk"));
46
- var debug_1 = __importDefault(require("debug"));
47
- var client_sqs_1 = require("@aws-sdk/client-sqs");
48
- var qrlCache_js_1 = require("./qrlCache.js");
49
- var sqs_js_1 = require("./sqs.js");
50
- var defaults_js_1 = require("./defaults.js");
51
- var exponentialBackoff_js_1 = require("./exponentialBackoff.js");
52
- var debug = (0, debug_1.default)('qdone:enqueue');
53
- function getOrCreateDLQ(queue, opt) {
54
- return __awaiter(this, void 0, void 0, function () {
55
- var dqname, dqrl, err_1, client, params, cmd, data, dqrl;
56
- return __generator(this, function (_a) {
57
- switch (_a.label) {
58
- case 0:
59
- debug('getOrCreateDLQ(', queue, ')');
60
- dqname = (0, qrlCache_js_1.normalizeDLQName)(queue, opt);
61
- _a.label = 1;
62
- case 1:
63
- _a.trys.push([1, 3, , 5]);
64
- return [4 /*yield*/, (0, qrlCache_js_1.qrlCacheGet)(dqname)];
65
- case 2:
66
- dqrl = _a.sent();
67
- return [2 /*return*/, dqrl];
68
- case 3:
69
- err_1 = _a.sent();
70
- // Anything other than queue doesn't exist gets re-thrown
71
- if (!(err_1 instanceof client_sqs_1.QueueDoesNotExist))
72
- throw err_1;
73
- client = (0, sqs_js_1.getSQSClient)();
74
- params = {
75
- Attributes: { MessageRetentionPeriod: opt.messageRetentionPeriod + '' },
76
- QueueName: dqname
77
- };
78
- if (opt.tags)
79
- params.tags = opt.tags;
80
- if (opt.fifo)
81
- params.Attributes.FifoQueue = 'true';
82
- cmd = new client_sqs_1.CreateQueueCommand(params);
83
- if (opt.verbose)
84
- console.error(chalk_1.default.blue('Creating dead letter queue ') + dqname);
85
- return [4 /*yield*/, client.send(cmd)];
86
- case 4:
87
- data = _a.sent();
88
- debug('createQueue returned', data);
89
- dqrl = data.QueueUrl;
90
- (0, qrlCache_js_1.qrlCacheSet)(dqname, dqrl);
91
- return [2 /*return*/, dqrl];
92
- case 5: return [2 /*return*/];
93
- }
94
- });
95
- });
7
+ const node_1 = require("@sentry/node");
8
+ const uuid_1 = require("uuid");
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const debug_1 = __importDefault(require("debug"));
11
+ const client_sqs_1 = require("@aws-sdk/client-sqs");
12
+ const qrlCache_js_1 = require("./qrlCache.js");
13
+ const sqs_js_1 = require("./sqs.js");
14
+ const defaults_js_1 = require("./defaults.js");
15
+ const exponentialBackoff_js_1 = require("./exponentialBackoff.js");
16
+ const debug = (0, debug_1.default)('qdone:enqueue');
17
+ async function getOrCreateDLQ(queue, opt) {
18
+ debug('getOrCreateDLQ(', queue, ')');
19
+ const dqname = (0, qrlCache_js_1.normalizeDLQName)(queue, opt);
20
+ try {
21
+ const dqrl = await (0, qrlCache_js_1.qrlCacheGet)(dqname);
22
+ return dqrl;
23
+ }
24
+ catch (err) {
25
+ // Anything other than queue doesn't exist gets re-thrown
26
+ if (!(err instanceof client_sqs_1.QueueDoesNotExist))
27
+ throw err;
28
+ // Create our DLQ
29
+ const client = (0, sqs_js_1.getSQSClient)();
30
+ const params = {
31
+ Attributes: { MessageRetentionPeriod: opt.messageRetentionPeriod + '' },
32
+ QueueName: dqname
33
+ };
34
+ if (opt.tags)
35
+ params.tags = opt.tags;
36
+ if (opt.fifo)
37
+ params.Attributes.FifoQueue = 'true';
38
+ const cmd = new client_sqs_1.CreateQueueCommand(params);
39
+ if (opt.verbose)
40
+ console.error(chalk_1.default.blue('Creating dead letter queue ') + dqname);
41
+ const data = await client.send(cmd);
42
+ debug('createQueue returned', data);
43
+ const dqrl = data.QueueUrl;
44
+ (0, qrlCache_js_1.qrlCacheSet)(dqname, dqrl);
45
+ return dqrl;
46
+ }
96
47
  }
97
48
  exports.getOrCreateDLQ = getOrCreateDLQ;
98
- function getOrCreateFailQueue(queue, opt) {
99
- return __awaiter(this, void 0, void 0, function () {
100
- var fqname, fqrl, err_2, client, params, dqrl, dqa, cmd, data, fqrl;
101
- return __generator(this, function (_a) {
102
- switch (_a.label) {
103
- case 0:
104
- debug('getOrCreateFailQueue(', queue, ')');
105
- fqname = (0, qrlCache_js_1.normalizeFailQueueName)(queue, opt);
106
- _a.label = 1;
107
- case 1:
108
- _a.trys.push([1, 3, , 8]);
109
- return [4 /*yield*/, (0, qrlCache_js_1.qrlCacheGet)(fqname)];
110
- case 2:
111
- fqrl = _a.sent();
112
- return [2 /*return*/, fqrl];
113
- case 3:
114
- err_2 = _a.sent();
115
- // Anything other than queue doesn't exist gets re-thrown
116
- if (!(err_2 instanceof client_sqs_1.QueueDoesNotExist))
117
- throw err_2;
118
- client = (0, sqs_js_1.getSQSClient)();
119
- params = {
120
- Attributes: { MessageRetentionPeriod: opt.messageRetentionPeriod + '' },
121
- QueueName: fqname
122
- };
123
- if (!opt.dlq) return [3 /*break*/, 6];
124
- return [4 /*yield*/, getOrCreateDLQ(queue, opt)];
125
- case 4:
126
- dqrl = _a.sent();
127
- return [4 /*yield*/, getQueueAttributes(dqrl)];
128
- case 5:
129
- dqa = _a.sent();
130
- debug('dqa', dqa);
131
- params.Attributes.RedrivePolicy = JSON.stringify({
132
- deadLetterTargetArn: dqa.Attributes.QueueArn,
133
- maxReceiveCount: opt.dlqAfter + ''
134
- });
135
- _a.label = 6;
136
- case 6:
137
- if (opt.failDelay)
138
- params.Attributes.DelaySeconds = opt.failDelay;
139
- if (opt.tags)
140
- params.tags = opt.tags;
141
- if (opt.fifo)
142
- params.Attributes.FifoQueue = 'true';
143
- cmd = new client_sqs_1.CreateQueueCommand(params);
144
- if (opt.verbose)
145
- console.error(chalk_1.default.blue('Creating fail queue ') + fqname);
146
- return [4 /*yield*/, client.send(cmd)];
147
- case 7:
148
- data = _a.sent();
149
- debug('createQueue returned', data);
150
- fqrl = data.QueueUrl;
151
- (0, qrlCache_js_1.qrlCacheSet)(fqname, fqrl);
152
- return [2 /*return*/, fqrl];
153
- case 8: return [2 /*return*/];
154
- }
155
- });
156
- });
49
+ async function getOrCreateFailQueue(queue, opt) {
50
+ debug('getOrCreateFailQueue(', queue, ')');
51
+ const fqname = (0, qrlCache_js_1.normalizeFailQueueName)(queue, opt);
52
+ try {
53
+ const fqrl = await (0, qrlCache_js_1.qrlCacheGet)(fqname);
54
+ return fqrl;
55
+ }
56
+ catch (err) {
57
+ // Anything other than queue doesn't exist gets re-thrown
58
+ if (!(err instanceof client_sqs_1.QueueDoesNotExist))
59
+ throw err;
60
+ // Crate our fail queue
61
+ const client = (0, sqs_js_1.getSQSClient)();
62
+ const params = {
63
+ Attributes: { MessageRetentionPeriod: opt.messageRetentionPeriod + '' },
64
+ QueueName: fqname
65
+ };
66
+ // If we have a dlq, we grab it and set a redrive policy
67
+ if (opt.dlq) {
68
+ const dqrl = await getOrCreateDLQ(queue, opt);
69
+ const dqa = await getQueueAttributes(dqrl);
70
+ debug('dqa', dqa);
71
+ params.Attributes.RedrivePolicy = JSON.stringify({
72
+ deadLetterTargetArn: dqa.Attributes.QueueArn,
73
+ maxReceiveCount: opt.dlqAfter + ''
74
+ });
75
+ }
76
+ if (opt.failDelay)
77
+ params.Attributes.DelaySeconds = opt.failDelay + '';
78
+ if (opt.tags)
79
+ params.tags = opt.tags;
80
+ if (opt.fifo)
81
+ params.Attributes.FifoQueue = 'true';
82
+ const cmd = new client_sqs_1.CreateQueueCommand(params);
83
+ if (opt.verbose)
84
+ console.error(chalk_1.default.blue('Creating fail queue ') + fqname);
85
+ const data = await client.send(cmd);
86
+ debug('createQueue returned', data);
87
+ const fqrl = data.QueueUrl;
88
+ (0, qrlCache_js_1.qrlCacheSet)(fqname, fqrl);
89
+ return fqrl;
90
+ }
157
91
  }
158
92
  exports.getOrCreateFailQueue = getOrCreateFailQueue;
159
93
  /**
160
94
  * Returns a qrl for a queue that either exists or does not
161
95
  */
162
- function getOrCreateQueue(queue, opt) {
163
- return __awaiter(this, void 0, void 0, function () {
164
- var qname, qrl, err_3, fqrl, fqa, client, params, cmd, data, qrl;
165
- return __generator(this, function (_a) {
166
- switch (_a.label) {
167
- case 0:
168
- debug('getOrCreateQueue(', queue, ')');
169
- qname = (0, qrlCache_js_1.normalizeQueueName)(queue, opt);
170
- _a.label = 1;
171
- case 1:
172
- _a.trys.push([1, 3, , 7]);
173
- return [4 /*yield*/, (0, qrlCache_js_1.qrlCacheGet)(qname)];
174
- case 2:
175
- qrl = _a.sent();
176
- return [2 /*return*/, qrl];
177
- case 3:
178
- err_3 = _a.sent();
179
- // Anything other than queue doesn't exist gets re-thrown
180
- if (!(err_3 instanceof client_sqs_1.QueueDoesNotExist))
181
- throw err_3;
182
- return [4 /*yield*/, getOrCreateFailQueue(qname, opt)];
183
- case 4:
184
- fqrl = _a.sent();
185
- return [4 /*yield*/, getQueueAttributes(fqrl)
186
- // Create our queue
187
- ];
188
- case 5:
189
- fqa = _a.sent();
190
- client = (0, sqs_js_1.getSQSClient)();
191
- params = {
192
- Attributes: {
193
- MessageRetentionPeriod: opt.messageRetentionPeriod + '',
194
- RedrivePolicy: JSON.stringify({
195
- deadLetterTargetArn: fqa.Attributes.QueueArn,
196
- maxReceiveCount: '1'
197
- })
198
- },
199
- QueueName: qname
200
- };
201
- if (opt.tags)
202
- params.tags = opt.tags;
203
- if (opt.fifo)
204
- params.Attributes.FifoQueue = 'true';
205
- cmd = new client_sqs_1.CreateQueueCommand(params);
206
- debug({ params: params });
207
- if (opt.verbose)
208
- console.error(chalk_1.default.blue('Creating queue ') + qname);
209
- return [4 /*yield*/, client.send(cmd)];
210
- case 6:
211
- data = _a.sent();
212
- debug('createQueue returned', data);
213
- qrl = data.QueueUrl;
214
- (0, qrlCache_js_1.qrlCacheSet)(qname, qrl);
215
- return [2 /*return*/, qrl];
216
- case 7: return [2 /*return*/];
217
- }
218
- });
219
- });
96
+ async function getOrCreateQueue(queue, opt) {
97
+ debug('getOrCreateQueue(', queue, ')');
98
+ const qname = (0, qrlCache_js_1.normalizeQueueName)(queue, opt);
99
+ try {
100
+ const qrl = await (0, qrlCache_js_1.qrlCacheGet)(qname);
101
+ return qrl;
102
+ }
103
+ catch (err) {
104
+ // Anything other than queue doesn't exist gets re-thrown
105
+ if (!(err instanceof client_sqs_1.QueueDoesNotExist))
106
+ throw err;
107
+ // Get our fail queue so we can create our own
108
+ const fqrl = await getOrCreateFailQueue(qname, opt);
109
+ const fqa = await getQueueAttributes(fqrl);
110
+ // Create our queue
111
+ const client = (0, sqs_js_1.getSQSClient)();
112
+ const params = {
113
+ Attributes: {
114
+ MessageRetentionPeriod: opt.messageRetentionPeriod + '',
115
+ RedrivePolicy: JSON.stringify({
116
+ deadLetterTargetArn: fqa.Attributes.QueueArn,
117
+ maxReceiveCount: '1'
118
+ })
119
+ },
120
+ QueueName: qname
121
+ };
122
+ if (opt.tags)
123
+ params.tags = opt.tags;
124
+ if (opt.fifo)
125
+ params.Attributes.FifoQueue = 'true';
126
+ const cmd = new client_sqs_1.CreateQueueCommand(params);
127
+ debug({ params });
128
+ if (opt.verbose)
129
+ console.error(chalk_1.default.blue('Creating queue ') + qname);
130
+ const data = await client.send(cmd);
131
+ debug('createQueue returned', data);
132
+ const qrl = data.QueueUrl;
133
+ (0, qrlCache_js_1.qrlCacheSet)(qname, qrl);
134
+ return qrl;
135
+ }
220
136
  }
221
137
  exports.getOrCreateQueue = getOrCreateQueue;
222
- function getQueueAttributes(qrl) {
223
- return __awaiter(this, void 0, void 0, function () {
224
- var client, params, cmd, data;
225
- return __generator(this, function (_a) {
226
- switch (_a.label) {
227
- case 0:
228
- debug('getQueueAttributes(', qrl, ')');
229
- client = (0, sqs_js_1.getSQSClient)();
230
- params = { AttributeNames: ['All'], QueueUrl: qrl };
231
- cmd = new client_sqs_1.GetQueueAttributesCommand(params);
232
- return [4 /*yield*/, client.send(cmd)];
233
- case 1:
234
- data = _a.sent();
235
- debug('GetQueueAttributes returned', data);
236
- return [2 /*return*/, data];
237
- }
238
- });
239
- });
138
+ async function getQueueAttributes(qrl) {
139
+ debug('getQueueAttributes(', qrl, ')');
140
+ const client = (0, sqs_js_1.getSQSClient)();
141
+ const params = { AttributeNames: ['All'], QueueUrl: qrl };
142
+ const cmd = new client_sqs_1.GetQueueAttributesCommand(params);
143
+ // debug({ cmd })
144
+ const data = await client.send(cmd);
145
+ debug('GetQueueAttributes returned', data);
146
+ return data;
240
147
  }
241
148
  exports.getQueueAttributes = getQueueAttributes;
242
149
  function formatMessage(command, id) {
243
- var message = {
150
+ const message = {
244
151
  /*
245
152
  MessageAttributes: {
246
153
  City: { DataType: 'String', StringValue: 'Any City' },
@@ -255,211 +162,155 @@ function formatMessage(command, id) {
255
162
  }
256
163
  exports.formatMessage = formatMessage;
257
164
  // Retry happens within the context of the send functions
258
- var retryableExceptions = [
165
+ const retryableExceptions = [
259
166
  client_sqs_1.RequestThrottled,
260
167
  client_sqs_1.KmsThrottled,
261
168
  client_sqs_1.QueueDoesNotExist // Queue could temporarily not exist due to eventual consistency, let it retry
262
169
  ];
263
- function sendMessage(qrl, command, opt) {
264
- return __awaiter(this, void 0, void 0, function () {
265
- var params, client, cmd, backoff, send, shouldRetry, result;
266
- var _this = this;
267
- return __generator(this, function (_a) {
268
- switch (_a.label) {
269
- case 0:
270
- debug('sendMessage(', qrl, command, ')');
271
- params = Object.assign({ QueueUrl: qrl }, formatMessage(command));
272
- if (opt.fifo) {
273
- params.MessageGroupId = opt.groupId;
274
- params.MessageDeduplicationId = opt.deduplicationId || (0, uuid_1.v1)();
275
- }
276
- if (opt.delay)
277
- params.DelaySeconds = opt.delay;
278
- client = (0, sqs_js_1.getSQSClient)();
279
- cmd = new client_sqs_1.SendMessageCommand(params);
280
- debug({ cmd: cmd });
281
- backoff = new exponentialBackoff_js_1.ExponentialBackoff(opt.sendRetries);
282
- send = function (attemptNumber) { return __awaiter(_this, void 0, void 0, function () {
283
- var data;
284
- return __generator(this, function (_a) {
285
- switch (_a.label) {
286
- case 0:
287
- cmd.input.attemptNumber = attemptNumber;
288
- return [4 /*yield*/, client.send(cmd)];
289
- case 1:
290
- data = _a.sent();
291
- debug('sendMessage returned', data);
292
- return [2 /*return*/, data];
293
- }
294
- });
295
- }); };
296
- shouldRetry = function (result, error) { return __awaiter(_this, void 0, void 0, function () {
297
- var _i, retryableExceptions_1, exceptionClass;
298
- return __generator(this, function (_a) {
299
- for (_i = 0, retryableExceptions_1 = retryableExceptions; _i < retryableExceptions_1.length; _i++) {
300
- exceptionClass = retryableExceptions_1[_i];
301
- if (error instanceof exceptionClass) {
302
- debug({ sendMessageRetryingBecause: { error: error, result: result } });
303
- return [2 /*return*/, true];
304
- }
305
- }
306
- return [2 /*return*/, false];
307
- });
308
- }); };
309
- return [4 /*yield*/, backoff.run(send, shouldRetry)];
310
- case 1:
311
- result = _a.sent();
312
- debug({ sendMessageResult: result });
313
- return [2 /*return*/, result];
170
+ async function sendMessage(qrl, command, opt) {
171
+ debug('sendMessage(', qrl, command, ')');
172
+ const params = Object.assign({ QueueUrl: qrl }, formatMessage(command));
173
+ if (opt.fifo) {
174
+ params.MessageGroupId = opt.groupId;
175
+ params.MessageDeduplicationId = opt.deduplicationId || (0, uuid_1.v1)();
176
+ }
177
+ if (opt.delay)
178
+ params.DelaySeconds = opt.delay;
179
+ // Send it
180
+ const client = (0, sqs_js_1.getSQSClient)();
181
+ const cmd = new client_sqs_1.SendMessageCommand(params);
182
+ debug({ cmd });
183
+ const backoff = new exponentialBackoff_js_1.ExponentialBackoff(opt.sendRetries);
184
+ const send = async (attemptNumber) => {
185
+ cmd.input.attemptNumber = attemptNumber;
186
+ const data = await client.send(cmd);
187
+ debug('sendMessage returned', data);
188
+ return data;
189
+ };
190
+ const shouldRetry = async (result, error) => {
191
+ for (const exceptionClass of retryableExceptions) {
192
+ if (error instanceof exceptionClass) {
193
+ debug({ sendMessageRetryingBecause: { error, result } });
194
+ return true;
314
195
  }
315
- });
316
- });
196
+ }
197
+ return false;
198
+ };
199
+ const result = await backoff.run(send, shouldRetry);
200
+ debug({ sendMessageResult: result });
201
+ return result;
317
202
  }
318
203
  exports.sendMessage = sendMessage;
319
- function sendMessageBatch(qrl, messages, opt) {
320
- return __awaiter(this, void 0, void 0, function () {
321
- var params, uuidFunction, client, cmd, backoff, send, shouldRetry;
322
- var _this = this;
323
- return __generator(this, function (_a) {
324
- debug('sendMessageBatch(', qrl, messages.map(function (e) { return Object.assign(Object.assign({}, e), { MessageBody: e.MessageBody.slice(0, 10) + '...' }); }), ')');
325
- params = { Entries: messages, QueueUrl: qrl };
326
- uuidFunction = opt.uuidFunction || uuid_1.v1;
327
- // Add in group id if we're using fifo
328
- if (opt.fifo) {
329
- params.Entries = params.Entries.map(function (message) { return Object.assign({
330
- MessageGroupId: opt.groupIdPerMessage ? uuidFunction() : opt.groupId,
331
- MessageDeduplicationId: opt.deduplicationId || uuidFunction()
332
- }, message); });
333
- }
334
- if (opt.delay) {
335
- params.Entries = params.Entries.map(function (message) {
336
- return Object.assign({ DelaySeconds: opt.delay }, message);
337
- });
338
- }
339
- if (opt.sentryDsn) {
340
- (0, node_1.addBreadcrumb)({ category: 'sendMessageBatch', message: JSON.stringify({ params: params }), level: 'debug' });
341
- }
342
- debug({ params: params });
343
- client = (0, sqs_js_1.getSQSClient)();
344
- cmd = new client_sqs_1.SendMessageBatchCommand(params);
345
- debug({ cmd: cmd });
346
- backoff = new exponentialBackoff_js_1.ExponentialBackoff(opt.sendRetries);
347
- send = function (attemptNumber) { return __awaiter(_this, void 0, void 0, function () {
348
- var data;
349
- return __generator(this, function (_a) {
350
- switch (_a.label) {
351
- case 0:
352
- debug({ sendMessageBatchSend: { attemptNumber: attemptNumber, params: params } });
353
- return [4 /*yield*/, client.send(cmd)];
354
- case 1:
355
- data = _a.sent();
356
- return [2 /*return*/, data];
357
- }
358
- });
359
- }); };
360
- shouldRetry = function (result, error) {
361
- debug({ shouldRetry: { error: error, result: result } });
362
- if (result) {
363
- // Handle failed result of one or more messages in the batch
364
- if (result.Failed && result.Failed.length) {
365
- var _loop_1 = function (failed) {
366
- // Find corresponding messages
367
- var original = params.Entries.find(function (e) { return e.Id === failed.Id; });
368
- var info = { failed: failed, original: original, opt: opt };
369
- if (opt.sentryDsn) {
370
- (0, node_1.addBreadcrumb)({ category: 'sendMessageBatch', message: 'Failed message: ' + JSON.stringify(info), level: 'error' });
371
- }
372
- else {
373
- console.error(info);
374
- }
375
- };
376
- for (var _i = 0, _a = result.Failed; _i < _a.length; _i++) {
377
- var failed = _a[_i];
378
- _loop_1(failed);
379
- }
380
- throw new Error('One or more message failures: ' + JSON.stringify(result.Failed));
381
- }
382
- }
383
- if (error) {
384
- // Handle a failed result from an overall error on request
204
+ async function sendMessageBatch(qrl, messages, opt) {
205
+ debug('sendMessageBatch(', qrl, messages.map(e => Object.assign(Object.assign({}, e), { MessageBody: e.MessageBody.slice(0, 10) + '...' })), ')');
206
+ const params = { Entries: messages, QueueUrl: qrl };
207
+ const uuidFunction = opt.uuidFunction || uuid_1.v1;
208
+ // Add in group id if we're using fifo
209
+ if (opt.fifo) {
210
+ params.Entries = params.Entries.map(message => Object.assign({
211
+ MessageGroupId: opt.groupIdPerMessage ? uuidFunction() : opt.groupId,
212
+ MessageDeduplicationId: opt.deduplicationId || uuidFunction()
213
+ }, message));
214
+ }
215
+ if (opt.delay) {
216
+ params.Entries = params.Entries.map(message => Object.assign({ DelaySeconds: opt.delay }, message));
217
+ }
218
+ if (opt.sentryDsn) {
219
+ (0, node_1.addBreadcrumb)({ category: 'sendMessageBatch', message: JSON.stringify({ params }), level: 'debug' });
220
+ }
221
+ debug({ params });
222
+ // Send them
223
+ const client = (0, sqs_js_1.getSQSClient)();
224
+ const cmd = new client_sqs_1.SendMessageBatchCommand(params);
225
+ debug({ cmd });
226
+ const backoff = new exponentialBackoff_js_1.ExponentialBackoff(opt.sendRetries);
227
+ const send = async (attemptNumber) => {
228
+ debug({ sendMessageBatchSend: { attemptNumber, params } });
229
+ const data = await client.send(cmd);
230
+ return data;
231
+ };
232
+ const shouldRetry = (result, error) => {
233
+ debug({ shouldRetry: { error, result } });
234
+ if (result) {
235
+ // Handle failed result of one or more messages in the batch
236
+ if (result.Failed && result.Failed.length) {
237
+ for (const failed of result.Failed) {
238
+ // Find corresponding messages
239
+ const original = params.Entries.find((e) => e.Id === failed.Id);
240
+ const info = { failed, original, opt };
385
241
  if (opt.sentryDsn) {
386
- (0, node_1.addBreadcrumb)({ category: 'sendMessageBatch', message: JSON.stringify({ error: error }), level: 'error' });
242
+ (0, node_1.addBreadcrumb)({ category: 'sendMessageBatch', message: 'Failed message: ' + JSON.stringify(info), level: 'error' });
387
243
  }
388
- for (var _b = 0, retryableExceptions_2 = retryableExceptions; _b < retryableExceptions_2.length; _b++) {
389
- var exceptionClass = retryableExceptions_2[_b];
390
- debug({ exceptionClass: exceptionClass, retryableExceptions: retryableExceptions });
391
- if (error instanceof exceptionClass) {
392
- debug({ sendMessageRetryingBecause: { error: error, result: result } });
393
- return true;
394
- }
244
+ else {
245
+ console.error(info);
395
246
  }
396
247
  }
397
- };
398
- return [2 /*return*/, backoff.run(send, shouldRetry)];
399
- });
400
- });
248
+ throw new Error('One or more message failures: ' + JSON.stringify(result.Failed));
249
+ }
250
+ }
251
+ if (error) {
252
+ // Handle a failed result from an overall error on request
253
+ if (opt.sentryDsn) {
254
+ (0, node_1.addBreadcrumb)({ category: 'sendMessageBatch', message: JSON.stringify({ error }), level: 'error' });
255
+ }
256
+ for (const exceptionClass of retryableExceptions) {
257
+ debug({ exceptionClass, retryableExceptions });
258
+ if (error instanceof exceptionClass) {
259
+ debug({ sendMessageRetryingBecause: { error, result } });
260
+ return true;
261
+ }
262
+ }
263
+ }
264
+ };
265
+ return backoff.run(send, shouldRetry);
401
266
  }
402
267
  exports.sendMessageBatch = sendMessageBatch;
403
- var requestCount = 0;
268
+ let requestCount = 0;
404
269
  //
405
270
  // Flushes the internal message buffer for qrl.
406
271
  // If the message is too large, batch is retried with half the messages.
407
272
  // Returns number of messages flushed.
408
273
  //
409
- function flushMessages(qrl, opt, sendBuffer) {
410
- return __awaiter(this, void 0, void 0, function () {
411
- function whileNotEmpty() {
412
- return __awaiter(this, void 0, void 0, function () {
413
- var batch, nextSize, totalSize, data, err;
414
- return __generator(this, function (_a) {
415
- switch (_a.label) {
416
- case 0:
417
- if (!(sendBuffer[qrl] && sendBuffer[qrl].length))
418
- return [2 /*return*/, numFlushed
419
- // Construct batch until full
420
- ];
421
- batch = [];
422
- nextSize = JSON.stringify(sendBuffer[qrl][0]).length;
423
- totalSize = 0;
424
- while ((totalSize + nextSize) < 262144 && sendBuffer[qrl].length && batch.length < 10) {
425
- batch.push(sendBuffer[qrl].shift());
426
- totalSize += nextSize;
427
- if (sendBuffer[qrl].length)
428
- nextSize = JSON.stringify(sendBuffer[qrl][0]).length;
429
- else
430
- nextSize = 0;
431
- }
432
- return [4 /*yield*/, sendMessageBatch(qrl, batch, opt)];
433
- case 1:
434
- data = _a.sent();
435
- debug({ data: data });
436
- // Fail if there are any individual message failures
437
- if (data.Failed && data.Failed.length) {
438
- err = new Error('One or more message failures: ' + JSON.stringify(data.Failed));
439
- err.Failed = data.Failed;
440
- throw err;
441
- }
442
- // If we actually managed to flush any of them
443
- if (batch.length) {
444
- requestCount += 1;
445
- data.Successful.forEach(function (message) {
446
- if (opt.verbose)
447
- console.error(chalk_1.default.blue('Enqueued job ') + message.MessageId + chalk_1.default.blue(' request ' + requestCount));
448
- });
449
- numFlushed += batch.length;
450
- }
451
- return [2 /*return*/, whileNotEmpty()];
452
- }
453
- });
274
+ async function flushMessages(qrl, opt, sendBuffer) {
275
+ debug('flushMessages', qrl);
276
+ // Flush until empty
277
+ let numFlushed = 0;
278
+ async function whileNotEmpty() {
279
+ if (!(sendBuffer[qrl] && sendBuffer[qrl].length))
280
+ return numFlushed;
281
+ // Construct batch until full
282
+ const batch = [];
283
+ let nextSize = JSON.stringify(sendBuffer[qrl][0]).length;
284
+ let totalSize = 0;
285
+ while ((totalSize + nextSize) < 262144 && sendBuffer[qrl].length && batch.length < 10) {
286
+ batch.push(sendBuffer[qrl].shift());
287
+ totalSize += nextSize;
288
+ if (sendBuffer[qrl].length)
289
+ nextSize = JSON.stringify(sendBuffer[qrl][0]).length;
290
+ else
291
+ nextSize = 0;
292
+ }
293
+ // Send batch
294
+ const data = await sendMessageBatch(qrl, batch, opt);
295
+ debug({ data });
296
+ // Fail if there are any individual message failures
297
+ if (data.Failed && data.Failed.length) {
298
+ const err = new Error('One or more message failures: ' + JSON.stringify(data.Failed));
299
+ err.Failed = data.Failed;
300
+ throw err;
301
+ }
302
+ // If we actually managed to flush any of them
303
+ if (batch.length) {
304
+ requestCount += 1;
305
+ data.Successful.forEach(message => {
306
+ if (opt.verbose)
307
+ console.error(chalk_1.default.blue('Enqueued job ') + message.MessageId + chalk_1.default.blue(' request ' + requestCount));
454
308
  });
309
+ numFlushed += batch.length;
455
310
  }
456
- var numFlushed;
457
- return __generator(this, function (_a) {
458
- debug('flushMessages', qrl);
459
- numFlushed = 0;
460
- return [2 /*return*/, whileNotEmpty()];
461
- });
462
- });
311
+ return whileNotEmpty();
312
+ }
313
+ return whileNotEmpty();
463
314
  }
464
315
  exports.flushMessages = flushMessages;
465
316
  //
@@ -467,111 +318,68 @@ exports.flushMessages = flushMessages;
467
318
  // Automaticaly flushes if queue has >= 10 messages.
468
319
  // Returns number of messages flushed.
469
320
  //
470
- function addMessage(qrl, command, messageIndex, opt, sendBuffer) {
471
- return __awaiter(this, void 0, void 0, function () {
472
- var message;
473
- return __generator(this, function (_a) {
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)];
480
- }
481
- return [2 /*return*/, 0];
482
- });
483
- });
321
+ async function addMessage(qrl, command, messageIndex, opt, sendBuffer) {
322
+ const message = formatMessage(command, messageIndex);
323
+ sendBuffer[qrl] = sendBuffer[qrl] || [];
324
+ sendBuffer[qrl].push(message);
325
+ debug({ location: 'addMessage', sendBuffer });
326
+ if (sendBuffer[qrl].length >= 10) {
327
+ return flushMessages(qrl, opt, sendBuffer);
328
+ }
329
+ return 0;
484
330
  }
485
331
  exports.addMessage = addMessage;
486
332
  //
487
333
  // Enqueue a single command
488
334
  // Returns a promise for the SQS API response.
489
335
  //
490
- function enqueue(queue, command, options) {
491
- return __awaiter(this, void 0, void 0, function () {
492
- var opt, qrl;
493
- return __generator(this, function (_a) {
494
- switch (_a.label) {
495
- case 0:
496
- debug('enqueue(', { queue: queue, command: command }, ')');
497
- opt = (0, defaults_js_1.getOptionsWithDefaults)(options);
498
- return [4 /*yield*/, getOrCreateQueue(queue, opt)];
499
- case 1:
500
- qrl = _a.sent();
501
- return [2 /*return*/, sendMessage(qrl, command, opt)];
502
- }
503
- });
504
- });
336
+ async function enqueue(queue, command, options) {
337
+ debug('enqueue(', { queue, command }, ')');
338
+ const opt = (0, defaults_js_1.getOptionsWithDefaults)(options);
339
+ const qrl = await getOrCreateQueue(queue, opt);
340
+ return sendMessage(qrl, command, opt);
505
341
  }
506
342
  exports.enqueue = enqueue;
507
343
  //
508
344
  // Enqueue many commands formatted as an array of {queue: ..., command: ...} pairs.
509
345
  // Returns a promise for the total number of messages enqueued.
510
346
  //
511
- function enqueueBatch(pairs, options) {
512
- return __awaiter(this, void 0, void 0, function () {
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;
514
- return __generator(this, function (_d) {
515
- switch (_d.label) {
516
- case 0:
517
- debug('enqueueBatch(', pairs, ')');
518
- opt = (0, defaults_js_1.getOptionsWithDefaults)(options);
519
- normalizedPairs = pairs.map(function (_a) {
520
- var queue = _a.queue, command = _a.command;
521
- return ({
522
- qname: (0, qrlCache_js_1.normalizeQueueName)(queue, opt),
523
- command: command
524
- });
525
- });
526
- uniqueQnames = new Set(normalizedPairs.map(function (p) { return p.qname; }));
527
- createPromises = [];
528
- for (_i = 0, uniqueQnames_1 = uniqueQnames; _i < uniqueQnames_1.length; _i++) {
529
- qname = uniqueQnames_1[_i];
530
- createPromises.push(getOrCreateQueue(qname, opt));
531
- }
532
- return [4 /*yield*/, Promise.all(createPromises)
533
- // After we've prefetched, all qrls are in cache
534
- // so go back through the list of pairs and fire off messages
535
- ];
536
- case 1:
537
- _d.sent();
538
- // After we've prefetched, all qrls are in cache
539
- // so go back through the list of pairs and fire off messages
540
- requestCount = 0;
541
- sendBuffer = {};
542
- messageIndex = 0;
543
- initialFlushTotal = 0;
544
- _a = 0, normalizedPairs_1 = normalizedPairs;
545
- _d.label = 2;
546
- case 2:
547
- if (!(_a < normalizedPairs_1.length)) return [3 /*break*/, 6];
548
- _b = normalizedPairs_1[_a], qname = _b.qname, command = _b.command;
549
- return [4 /*yield*/, getOrCreateQueue(qname, opt)];
550
- case 3:
551
- qrl = _d.sent();
552
- _c = initialFlushTotal;
553
- return [4 /*yield*/, addMessage(qrl, command, messageIndex++, opt, sendBuffer)];
554
- case 4:
555
- initialFlushTotal = _c + _d.sent();
556
- _d.label = 5;
557
- case 5:
558
- _a++;
559
- return [3 /*break*/, 2];
560
- case 6:
561
- extraFlushPromises = [];
562
- for (qrl in sendBuffer) {
563
- extraFlushPromises.push(flushMessages(qrl, opt, sendBuffer));
564
- }
565
- return [4 /*yield*/, Promise.all(extraFlushPromises)];
566
- case 7:
567
- extraFlushCounts = _d.sent();
568
- extraFlushTotal = extraFlushCounts.reduce(function (a, b) { return a + b; }, 0);
569
- totalFlushed = initialFlushTotal + extraFlushTotal;
570
- debug({ initialFlushTotal: initialFlushTotal, extraFlushTotal: extraFlushTotal, totalFlushed: totalFlushed });
571
- return [2 /*return*/, totalFlushed];
572
- }
573
- });
574
- });
347
+ async function enqueueBatch(pairs, options) {
348
+ debug('enqueueBatch(', pairs, ')');
349
+ const opt = (0, defaults_js_1.getOptionsWithDefaults)(options);
350
+ // Find unique queues so we can pre-fetch qrls. We do this so that all
351
+ // queues are created prior to going through our flush logic
352
+ const normalizedPairs = pairs.map(({ queue, command }) => ({
353
+ qname: (0, qrlCache_js_1.normalizeQueueName)(queue, opt),
354
+ command
355
+ }));
356
+ const uniqueQnames = new Set(normalizedPairs.map(p => p.qname));
357
+ // Prefetch qrls / create queues in parallel
358
+ const createPromises = [];
359
+ for (const qname of uniqueQnames) {
360
+ createPromises.push(getOrCreateQueue(qname, opt));
361
+ }
362
+ await Promise.all(createPromises);
363
+ // After we've prefetched, all qrls are in cache
364
+ // so go back through the list of pairs and fire off messages
365
+ requestCount = 0;
366
+ const sendBuffer = {};
367
+ let messageIndex = 0;
368
+ let initialFlushTotal = 0;
369
+ for (const { qname, command } of normalizedPairs) {
370
+ const qrl = await getOrCreateQueue(qname, opt);
371
+ initialFlushTotal += await addMessage(qrl, command, messageIndex++, opt, sendBuffer);
372
+ }
373
+ // And flush any remaining messages
374
+ const extraFlushPromises = [];
375
+ for (const qrl in sendBuffer) {
376
+ extraFlushPromises.push(flushMessages(qrl, opt, sendBuffer));
377
+ }
378
+ const extraFlushCounts = await Promise.all(extraFlushPromises);
379
+ const extraFlushTotal = extraFlushCounts.reduce((a, b) => a + b, 0);
380
+ const totalFlushed = initialFlushTotal + extraFlushTotal;
381
+ debug({ initialFlushTotal, extraFlushTotal, totalFlushed });
382
+ return totalFlushed;
575
383
  }
576
384
  exports.enqueueBatch = enqueueBatch;
577
385
  debug('loaded');