qdone 2.0.35-alpha → 2.0.37-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.
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
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;
6
+ exports.enqueueBatch = exports.enqueue = exports.addMessage = exports.flushMessages = exports.sendMessageBatch = exports.sendMessage = exports.formatMessage = exports.getQueueAttributes = exports.getOrCreateQueue = exports.getQueueParams = exports.getOrCreateFailQueue = exports.getFailParams = exports.getOrCreateDLQ = exports.getDLQParams = void 0;
7
7
  const node_1 = require("@sentry/node");
8
8
  const uuid_1 = require("uuid");
9
9
  const chalk_1 = __importDefault(require("chalk"));
@@ -11,12 +11,26 @@ const debug_1 = __importDefault(require("debug"));
11
11
  const client_sqs_1 = require("@aws-sdk/client-sqs");
12
12
  const qrlCache_js_1 = require("./qrlCache.js");
13
13
  const sqs_js_1 = require("./sqs.js");
14
+ const dedup_js_1 = require("./dedup.js");
14
15
  const defaults_js_1 = require("./defaults.js");
15
16
  const exponentialBackoff_js_1 = require("./exponentialBackoff.js");
16
17
  const debug = (0, debug_1.default)('qdone:enqueue');
18
+ function getDLQParams(queue, opt) {
19
+ const dqname = (0, qrlCache_js_1.normalizeDLQName)(queue, opt);
20
+ const params = {
21
+ Attributes: { MessageRetentionPeriod: opt.messageRetentionPeriod + '' },
22
+ QueueName: dqname
23
+ };
24
+ if (opt.tags)
25
+ params.tags = opt.tags;
26
+ if (opt.fifo)
27
+ params.Attributes.FifoQueue = 'true';
28
+ return { dqname, params };
29
+ }
30
+ exports.getDLQParams = getDLQParams;
17
31
  async function getOrCreateDLQ(queue, opt) {
18
32
  debug('getOrCreateDLQ(', queue, ')');
19
- const dqname = (0, qrlCache_js_1.normalizeDLQName)(queue, opt);
33
+ const { dqname, params } = getDLQParams(queue, opt);
20
34
  try {
21
35
  const dqrl = await (0, qrlCache_js_1.qrlCacheGet)(dqname);
22
36
  return dqrl;
@@ -27,14 +41,6 @@ async function getOrCreateDLQ(queue, opt) {
27
41
  throw err;
28
42
  // Create our DLQ
29
43
  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
44
  const cmd = new client_sqs_1.CreateQueueCommand(params);
39
45
  if (opt.verbose)
40
46
  console.error(chalk_1.default.blue('Creating dead letter queue ') + dqname);
@@ -46,10 +52,47 @@ async function getOrCreateDLQ(queue, opt) {
46
52
  }
47
53
  }
48
54
  exports.getOrCreateDLQ = getOrCreateDLQ;
49
- async function getOrCreateFailQueue(queue, opt) {
55
+ /**
56
+ * Returns the parameters needed for creating a failed queue. If DLQ options
57
+ * are set, it makes an API call to get this DLQ's ARN.
58
+ */
59
+ async function getFailParams(queue, opt) {
60
+ const fqname = (0, qrlCache_js_1.normalizeFailQueueName)(queue, opt);
61
+ const params = {
62
+ Attributes: { MessageRetentionPeriod: opt.messageRetentionPeriod + '' },
63
+ QueueName: fqname
64
+ };
65
+ // If we have a dlq, we grab it and set a redrive policy
66
+ if (opt.dlq) {
67
+ const dqname = (0, qrlCache_js_1.normalizeDLQName)(queue, opt);
68
+ const dqrl = await (0, qrlCache_js_1.qrlCacheGet)(dqname);
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
+ return params;
83
+ }
84
+ exports.getFailParams = getFailParams;
85
+ /**
86
+ * Returns the qrl for the failed queue for the given queue. Creates the queue
87
+ * if it does not exist.
88
+ */
89
+ async function getOrCreateFailQueue(queue, opt, doesNotExist) {
50
90
  debug('getOrCreateFailQueue(', queue, ')');
51
91
  const fqname = (0, qrlCache_js_1.normalizeFailQueueName)(queue, opt);
52
92
  try {
93
+ // Bail early if the caller knew we didn't have a queue
94
+ if (doesNotExist)
95
+ throw new client_sqs_1.QueueDoesNotExist(fqname);
53
96
  const fqrl = await (0, qrlCache_js_1.qrlCacheGet)(fqname);
54
97
  return fqrl;
55
98
  }
@@ -57,28 +100,20 @@ async function getOrCreateFailQueue(queue, opt) {
57
100
  // Anything other than queue doesn't exist gets re-thrown
58
101
  if (!(err instanceof client_sqs_1.QueueDoesNotExist))
59
102
  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
- });
103
+ // Grab params, creating DLQ if needed
104
+ let params;
105
+ try {
106
+ params = await getFailParams(queue, opt);
75
107
  }
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';
108
+ catch (e) {
109
+ // If DLQ doesn't exist, create it
110
+ if (!(opt.dlq && e instanceof client_sqs_1.QueueDoesNotExist))
111
+ throw e;
112
+ await getOrCreateDLQ(queue, opt);
113
+ params = await getFailParams(queue, opt);
114
+ }
115
+ // Create our fail queue
116
+ const client = (0, sqs_js_1.getSQSClient)();
82
117
  const cmd = new client_sqs_1.CreateQueueCommand(params);
83
118
  if (opt.verbose)
84
119
  console.error(chalk_1.default.blue('Creating fail queue ') + fqname);
@@ -90,6 +125,32 @@ async function getOrCreateFailQueue(queue, opt) {
90
125
  }
91
126
  }
92
127
  exports.getOrCreateFailQueue = getOrCreateFailQueue;
128
+ /**
129
+ * Returns the parameters needed for creating a queue. If fail options
130
+ * are set, it makes an API call to get the fail queue's ARN.
131
+ */
132
+ async function getQueueParams(queue, opt) {
133
+ const qname = (0, qrlCache_js_1.normalizeQueueName)(queue, opt);
134
+ const fqname = (0, qrlCache_js_1.normalizeFailQueueName)(queue, opt);
135
+ const fqrl = await (0, qrlCache_js_1.qrlCacheGet)(fqname, opt);
136
+ const fqa = await getQueueAttributes(fqrl);
137
+ const params = {
138
+ Attributes: {
139
+ MessageRetentionPeriod: opt.messageRetentionPeriod + '',
140
+ RedrivePolicy: JSON.stringify({
141
+ deadLetterTargetArn: fqa.Attributes.QueueArn,
142
+ maxReceiveCount: 1
143
+ })
144
+ },
145
+ QueueName: qname
146
+ };
147
+ if (opt.tags)
148
+ params.tags = opt.tags;
149
+ if (opt.fifo)
150
+ params.Attributes.FifoQueue = 'true';
151
+ return params;
152
+ }
153
+ exports.getQueueParams = getQueueParams;
93
154
  /**
94
155
  * Returns a qrl for a queue that either exists or does not
95
156
  */
@@ -104,31 +165,26 @@ async function getOrCreateQueue(queue, opt) {
104
165
  // Anything other than queue doesn't exist gets re-thrown
105
166
  if (!(err instanceof client_sqs_1.QueueDoesNotExist))
106
167
  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);
168
+ // Grab params, creating fail queue if needed
169
+ let params;
170
+ try {
171
+ params = await getQueueParams(qname, opt);
172
+ }
173
+ catch (e) {
174
+ // If fail queue doesn't exist, create it
175
+ if (!(e instanceof client_sqs_1.QueueDoesNotExist))
176
+ throw e;
177
+ await getOrCreateFailQueue(qname, opt, true);
178
+ params = await getQueueParams(qname, opt);
179
+ }
180
+ debug({ getOrCreateQueue: { qname, params } });
110
181
  // Create our queue
111
182
  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
183
  const cmd = new client_sqs_1.CreateQueueCommand(params);
127
- debug({ params });
128
184
  if (opt.verbose)
129
- console.error(chalk_1.default.blue('Creating queue ') + qname);
185
+ console.error(chalk_1.default.blue('Creating fail queue ') + qname);
130
186
  const data = await client.send(cmd);
131
- debug('createQueue returned', data);
187
+ debug('AWS createQueue returned', data);
132
188
  const qrl = data.QueueUrl;
133
189
  (0, qrlCache_js_1.qrlCacheSet)(qname, qrl);
134
190
  return qrl;
@@ -146,18 +202,18 @@ async function getQueueAttributes(qrl) {
146
202
  return data;
147
203
  }
148
204
  exports.getQueueAttributes = getQueueAttributes;
149
- function formatMessage(command, id) {
150
- const message = {
151
- /*
152
- MessageAttributes: {
153
- City: { DataType: 'String', StringValue: 'Any City' },
154
- Population: { DataType: 'Number', StringValue: '1250800' }
155
- },
156
- */
157
- MessageBody: command
158
- };
205
+ function formatMessage(body, id, opt, messageOptions) {
206
+ const message = { MessageBody: body };
159
207
  if (typeof id !== 'undefined')
160
208
  message.Id = '' + id;
209
+ if (opt.fifo) {
210
+ message.MessageGroupId = messageOptions?.groupId || opt?.groupId;
211
+ }
212
+ (0, dedup_js_1.addDedupParamsToMessage)(message, opt, messageOptions);
213
+ if (opt.delay)
214
+ message.DelaySeconds = opt.delay;
215
+ if (messageOptions?.delay)
216
+ message.DelaySeconds = messageOptions.delay;
161
217
  return message;
162
218
  }
163
219
  exports.formatMessage = formatMessage;
@@ -167,15 +223,19 @@ const retryableExceptions = [
167
223
  client_sqs_1.KmsThrottled,
168
224
  client_sqs_1.QueueDoesNotExist // Queue could temporarily not exist due to eventual consistency, let it retry
169
225
  ];
170
- async function sendMessage(qrl, command, opt) {
226
+ async function sendMessage(qrl, command, opt, messageOptions) {
171
227
  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)();
228
+ const uuidFunction = opt.uuidFunction || uuid_1.v1;
229
+ const params = {
230
+ QueueUrl: qrl,
231
+ ...formatMessage(command, null, opt, messageOptions)
232
+ };
233
+ // See if we even have to send it
234
+ if (opt.externalDedup) {
235
+ const shouldEnqueue = await (0, dedup_js_1.dedupShouldEnqueue)(params, opt);
236
+ if (!shouldEnqueue)
237
+ return { MessageId: uuidFunction() };
176
238
  }
177
- if (opt.delay)
178
- params.DelaySeconds = opt.delay;
179
239
  // Send it
180
240
  const client = (0, sqs_js_1.getSQSClient)();
181
241
  const cmd = new client_sqs_1.SendMessageCommand(params);
@@ -188,12 +248,16 @@ async function sendMessage(qrl, command, opt) {
188
248
  return data;
189
249
  };
190
250
  const shouldRetry = async (result, error) => {
251
+ if (!error)
252
+ return false;
191
253
  for (const exceptionClass of retryableExceptions) {
192
254
  if (error instanceof exceptionClass) {
193
255
  debug({ sendMessageRetryingBecause: { error, result } });
194
256
  return true;
195
257
  }
196
258
  }
259
+ // If we could not send it, we also need to remove our dedup flag
260
+ await (0, dedup_js_1.dedupSuccessfullyProcessed)(params, opt);
197
261
  return false;
198
262
  };
199
263
  const result = await backoff.run(send, shouldRetry);
@@ -204,21 +268,18 @@ exports.sendMessage = sendMessage;
204
268
  async function sendMessageBatch(qrl, messages, opt) {
205
269
  debug('sendMessageBatch(', qrl, messages.map(e => Object.assign(Object.assign({}, e), { MessageBody: e.MessageBody.slice(0, 10) + '...' })), ')');
206
270
  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
271
  if (opt.sentryDsn) {
219
272
  (0, node_1.addBreadcrumb)({ category: 'sendMessageBatch', message: JSON.stringify({ params }), level: 'debug' });
220
273
  }
221
274
  debug({ params });
275
+ // See which messages we even have to send
276
+ if (opt.externalDedup) {
277
+ const promises = params.Entries.map(async (m) => ({ m, shouldEnqueue: await (0, dedup_js_1.dedupShouldEnqueue)(m, opt) }));
278
+ const results = await Promise.all(promises);
279
+ params.Entries = results.filter(({ shouldEnqueue }) => shouldEnqueue);
280
+ if (!params.Entries.length)
281
+ return;
282
+ }
222
283
  // Send them
223
284
  const client = (0, sqs_js_1.getSQSClient)();
224
285
  const cmd = new client_sqs_1.SendMessageBatchCommand(params);
@@ -318,8 +379,8 @@ exports.flushMessages = flushMessages;
318
379
  // Automaticaly flushes if queue has >= 10 messages.
319
380
  // Returns number of messages flushed.
320
381
  //
321
- async function addMessage(qrl, command, messageIndex, opt, sendBuffer) {
322
- const message = formatMessage(command, messageIndex);
382
+ async function addMessage(qrl, command, messageIndex, opt, sendBuffer, messageOptions) {
383
+ const message = formatMessage(command, messageIndex, opt, messageOptions);
323
384
  sendBuffer[qrl] = sendBuffer[qrl] || [];
324
385
  sendBuffer[qrl].push(message);
325
386
  debug({ location: 'addMessage', sendBuffer });
@@ -336,8 +397,17 @@ exports.addMessage = addMessage;
336
397
  async function enqueue(queue, command, options) {
337
398
  debug('enqueue(', { queue, command }, ')');
338
399
  const opt = (0, defaults_js_1.getOptionsWithDefaults)(options);
339
- const qrl = await getOrCreateQueue(queue, opt);
340
- return sendMessage(qrl, command, opt);
400
+ if (opt.sentryDsn) {
401
+ (0, node_1.setExtra)({ qdoneOperation: 'enqueue', args: { queue, command, opt } });
402
+ }
403
+ try {
404
+ const qrl = await getOrCreateQueue(queue, opt);
405
+ return sendMessage(qrl, command, opt);
406
+ }
407
+ catch (e) {
408
+ console.log(e);
409
+ throw e;
410
+ }
341
411
  }
342
412
  exports.enqueue = enqueue;
343
413
  //
@@ -347,39 +417,49 @@ exports.enqueue = enqueue;
347
417
  async function enqueueBatch(pairs, options) {
348
418
  debug('enqueueBatch(', pairs, ')');
349
419
  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));
420
+ if (opt.sentryDsn) {
421
+ (0, node_1.setExtra)({ qdoneOperation: 'enqueueBatch', args: { pairs, opt } });
361
422
  }
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);
423
+ try {
424
+ // Find unique queues so we can pre-fetch qrls. We do this so that all
425
+ // queues are created prior to going through our flush logic
426
+ const normalizedPairs = pairs.map(({ queue, command, messageOptions }) => ({
427
+ qname: (0, qrlCache_js_1.normalizeQueueName)(queue, opt),
428
+ command,
429
+ messageOptions: (0, defaults_js_1.validateMessageOptions)(messageOptions)
430
+ }));
431
+ const uniqueQnames = new Set(normalizedPairs.map(p => p.qname));
432
+ // Prefetch qrls / create queues in parallel
433
+ const createPromises = [];
434
+ for (const qname of uniqueQnames) {
435
+ createPromises.push(getOrCreateQueue(qname, opt));
436
+ }
437
+ await Promise.all(createPromises);
438
+ // After we've prefetched, all qrls are in cache
439
+ // so go back through the list of pairs and fire off messages
440
+ requestCount = 0;
441
+ const sendBuffer = {};
442
+ let messageIndex = 0;
443
+ let initialFlushTotal = 0;
444
+ for (const { qname, command, messageOptions } of normalizedPairs) {
445
+ const qrl = await getOrCreateQueue(qname, opt);
446
+ initialFlushTotal += await addMessage(qrl, command, messageIndex++, opt, sendBuffer, messageOptions);
447
+ }
448
+ // And flush any remaining messages
449
+ const extraFlushPromises = [];
450
+ for (const qrl in sendBuffer) {
451
+ extraFlushPromises.push(flushMessages(qrl, opt, sendBuffer));
452
+ }
453
+ const extraFlushCounts = await Promise.all(extraFlushPromises);
454
+ const extraFlushTotal = extraFlushCounts.reduce((a, b) => a + b, 0);
455
+ const totalFlushed = initialFlushTotal + extraFlushTotal;
456
+ debug({ initialFlushTotal, extraFlushTotal, totalFlushed });
457
+ return totalFlushed;
372
458
  }
373
- // And flush any remaining messages
374
- const extraFlushPromises = [];
375
- for (const qrl in sendBuffer) {
376
- extraFlushPromises.push(flushMessages(qrl, opt, sendBuffer));
459
+ catch (e) {
460
+ console.log(e);
461
+ throw e;
377
462
  }
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;
383
463
  }
384
464
  exports.enqueueBatch = enqueueBatch;
385
465
  debug('loaded');
@@ -70,7 +70,8 @@ async function qrlCacheGet(qname) {
70
70
  // debug({ cmd })
71
71
  const result = await client.send(cmd);
72
72
  // debug('result', result)
73
- // if (!result) throw new Error(`No such queue ${qname}`)
73
+ if (!result)
74
+ throw new client_sqs_1.QueueDoesNotExist(qname);
74
75
  const { QueueUrl: qrl } = result;
75
76
  // debug('getQueueUrl returned', data)
76
77
  qcache.set(qname, qrl);
@@ -11,6 +11,7 @@ exports.JobExecutor = void 0;
11
11
  const client_sqs_1 = require("@aws-sdk/client-sqs");
12
12
  const chalk_1 = __importDefault(require("chalk"));
13
13
  const debug_1 = __importDefault(require("debug"));
14
+ const dedup_js_1 = require("../dedup.js");
14
15
  const sqs_js_1 = require("../sqs.js");
15
16
  const debug = (0, debug_1.default)('qdone:jobExecutor');
16
17
  const maxJobSeconds = 12 * 60 * 60;
@@ -217,6 +218,8 @@ class JobExecutor {
217
218
  }
218
219
  }
219
220
  debug('DeleteMessageBatch returned', result);
221
+ // Mark batch as processed for dedup
222
+ await Promise.all(entries.map(e => (0, dedup_js_1.dedupSuccessfullyProcessed)(this.jobsByMessageId[e.Id], this.opt)));
220
223
  // TODO Sentry
221
224
  }
222
225
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qdone",
3
- "version": "2.0.35-alpha",
3
+ "version": "2.0.37-alpha",
4
4
  "description": "A distributed scheduler for SQS",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -21,6 +21,7 @@
21
21
  "command-line-usage": "^7.0.1",
22
22
  "debug": "^4.3.4",
23
23
  "ioredis": "^5.3.2",
24
+ "ioredis-mock": "^8.9.0",
24
25
  "standard": "^17.1.0",
25
26
  "tree-kill": "^1.2.2",
26
27
  "uuid": "^9.0.1"
@@ -50,7 +51,7 @@
50
51
  "build": "tsc --allowJs index.js --outdir commonjs --esModuleInterop --module commonjs --target es2021 --strict --skipLibCheck --forceConsistentCasingInFileNames",
51
52
  "clean": "rm -rf commonjs/src commonjs/*.js coverage",
52
53
  "lint": "standard",
53
- "coverage": "nyc report --reporter=text-lcov | coveralls",
54
+ "coverage": "NODE_OPTIONS='--experimental-json-modules --experimental-vm-modules --no-warnings' jest --coverage | coveralls",
54
55
  "standard": "standard",
55
56
  "prep-for-publish": "echo YOU MUST USE NPM TO PREP FOR PUBLISH && pnpm run clean && pnpm run build && npm shrinkwrap --production && echo now commit shrinkwrap and use npm run publish-{next,latest}",
56
57
  "publish-latest": "npm publish --tag latest",
package/src/cache.js CHANGED
@@ -12,15 +12,16 @@ let client
12
12
  * how to connect.
13
13
  */
14
14
  export function getCacheClient (opt) {
15
+ const RedisClass = opt.Redis || Redis
15
16
  if (client) {
16
17
  return client
17
18
  } else if (opt.cacheUri) {
18
19
  const url = new URL(opt.cacheUri)
19
20
  if (url.protocol === 'redis:') {
20
- client = new Redis(url.toString())
21
+ client = new RedisClass(url.toString())
21
22
  } else if (url.protocol === 'redis-cluster:') {
22
23
  url.protocol = 'redis:'
23
- client = new Redis.Cluster([url.toString()], { slotsRefreshInterval: 60 * 1000 })
24
+ client = new RedisClass.Cluster([url.toString()], { slotsRefreshInterval: 60 * 1000 })
24
25
  } else {
25
26
  throw new UsageError(`Only redis:// or redis-cluster:// URLs are currently supported. Got: ${url.protocol}`)
26
27
  }