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.
- package/commonjs/src/cache.js +3 -2
- package/commonjs/src/dedup.js +261 -0
- package/commonjs/src/defaults.js +39 -4
- package/commonjs/src/enqueue.js +194 -114
- package/commonjs/src/qrlCache.js +2 -1
- package/commonjs/src/scheduler/jobExecutor.js +3 -0
- package/package.json +3 -2
- package/src/cache.js +3 -2
- package/src/check.js +205 -0
- package/src/cli.js +81 -3
- package/src/dedup.js +252 -0
- package/src/defaults.js +37 -3
- package/src/enqueue.js +186 -114
- package/src/qrlCache.js +1 -1
- package/src/scheduler/jobExecutor.js +5 -0
- package/src/worker.js +6 -0
- package/npm-shrinkwrap.json +0 -15999
package/src/enqueue.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addBreadcrumb } from '@sentry/node'
|
|
1
|
+
import { addBreadcrumb, setExtra } from '@sentry/node'
|
|
2
2
|
import { v1 as uuidV1 } from 'uuid'
|
|
3
3
|
import chalk from 'chalk'
|
|
4
4
|
import Debug from 'debug'
|
|
@@ -20,14 +20,30 @@ import {
|
|
|
20
20
|
normalizeDLQName
|
|
21
21
|
} from './qrlCache.js'
|
|
22
22
|
import { getSQSClient } from './sqs.js'
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
addDedupParamsToMessage,
|
|
25
|
+
dedupShouldEnqueue,
|
|
26
|
+
dedupSuccessfullyProcessed
|
|
27
|
+
} from './dedup.js'
|
|
28
|
+
import { getOptionsWithDefaults, validateMessageOptions } from './defaults.js'
|
|
24
29
|
import { ExponentialBackoff } from './exponentialBackoff.js'
|
|
25
30
|
|
|
26
31
|
const debug = Debug('qdone:enqueue')
|
|
27
32
|
|
|
33
|
+
export function getDLQParams (queue, opt) {
|
|
34
|
+
const dqname = normalizeDLQName(queue, opt)
|
|
35
|
+
const params = {
|
|
36
|
+
Attributes: { MessageRetentionPeriod: opt.messageRetentionPeriod + '' },
|
|
37
|
+
QueueName: dqname
|
|
38
|
+
}
|
|
39
|
+
if (opt.tags) params.tags = opt.tags
|
|
40
|
+
if (opt.fifo) params.Attributes.FifoQueue = 'true'
|
|
41
|
+
return { dqname, params }
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
export async function getOrCreateDLQ (queue, opt) {
|
|
29
45
|
debug('getOrCreateDLQ(', queue, ')')
|
|
30
|
-
const dqname =
|
|
46
|
+
const { dqname, params } = getDLQParams(queue, opt)
|
|
31
47
|
try {
|
|
32
48
|
const dqrl = await qrlCacheGet(dqname)
|
|
33
49
|
return dqrl
|
|
@@ -37,12 +53,6 @@ export async function getOrCreateDLQ (queue, opt) {
|
|
|
37
53
|
|
|
38
54
|
// Create our DLQ
|
|
39
55
|
const client = getSQSClient()
|
|
40
|
-
const params = {
|
|
41
|
-
Attributes: { MessageRetentionPeriod: opt.messageRetentionPeriod + '' },
|
|
42
|
-
QueueName: dqname
|
|
43
|
-
}
|
|
44
|
-
if (opt.tags) params.tags = opt.tags
|
|
45
|
-
if (opt.fifo) params.Attributes.FifoQueue = 'true'
|
|
46
56
|
const cmd = new CreateQueueCommand(params)
|
|
47
57
|
if (opt.verbose) console.error(chalk.blue('Creating dead letter queue ') + dqname)
|
|
48
58
|
const data = await client.send(cmd)
|
|
@@ -53,35 +63,62 @@ export async function getOrCreateDLQ (queue, opt) {
|
|
|
53
63
|
}
|
|
54
64
|
}
|
|
55
65
|
|
|
56
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Returns the parameters needed for creating a failed queue. If DLQ options
|
|
68
|
+
* are set, it makes an API call to get this DLQ's ARN.
|
|
69
|
+
*/
|
|
70
|
+
export async function getFailParams (queue, opt) {
|
|
71
|
+
const fqname = normalizeFailQueueName(queue, opt)
|
|
72
|
+
const params = {
|
|
73
|
+
Attributes: { MessageRetentionPeriod: opt.messageRetentionPeriod + '' },
|
|
74
|
+
QueueName: fqname
|
|
75
|
+
}
|
|
76
|
+
// If we have a dlq, we grab it and set a redrive policy
|
|
77
|
+
if (opt.dlq) {
|
|
78
|
+
const dqname = normalizeDLQName(queue, opt)
|
|
79
|
+
const dqrl = await qrlCacheGet(dqname)
|
|
80
|
+
const dqa = await getQueueAttributes(dqrl)
|
|
81
|
+
debug('dqa', dqa)
|
|
82
|
+
params.Attributes.RedrivePolicy = JSON.stringify({
|
|
83
|
+
deadLetterTargetArn: dqa.Attributes.QueueArn,
|
|
84
|
+
maxReceiveCount: opt.dlqAfter
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
if (opt.failDelay) params.Attributes.DelaySeconds = opt.failDelay + ''
|
|
88
|
+
if (opt.tags) params.tags = opt.tags
|
|
89
|
+
if (opt.fifo) params.Attributes.FifoQueue = 'true'
|
|
90
|
+
return params
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Returns the qrl for the failed queue for the given queue. Creates the queue
|
|
95
|
+
* if it does not exist.
|
|
96
|
+
*/
|
|
97
|
+
export async function getOrCreateFailQueue (queue, opt, doesNotExist) {
|
|
57
98
|
debug('getOrCreateFailQueue(', queue, ')')
|
|
58
99
|
const fqname = normalizeFailQueueName(queue, opt)
|
|
59
100
|
try {
|
|
101
|
+
// Bail early if the caller knew we didn't have a queue
|
|
102
|
+
if (doesNotExist) throw new QueueDoesNotExist(fqname)
|
|
60
103
|
const fqrl = await qrlCacheGet(fqname)
|
|
61
104
|
return fqrl
|
|
62
105
|
} catch (err) {
|
|
63
106
|
// Anything other than queue doesn't exist gets re-thrown
|
|
64
107
|
if (!(err instanceof QueueDoesNotExist)) throw err
|
|
65
108
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const dqa = await getQueueAttributes(dqrl)
|
|
76
|
-
debug('dqa', dqa)
|
|
77
|
-
params.Attributes.RedrivePolicy = JSON.stringify({
|
|
78
|
-
deadLetterTargetArn: dqa.Attributes.QueueArn,
|
|
79
|
-
maxReceiveCount: opt.dlqAfter + ''
|
|
80
|
-
})
|
|
109
|
+
// Grab params, creating DLQ if needed
|
|
110
|
+
let params
|
|
111
|
+
try {
|
|
112
|
+
params = await getFailParams(queue, opt)
|
|
113
|
+
} catch (e) {
|
|
114
|
+
// If DLQ doesn't exist, create it
|
|
115
|
+
if (!(opt.dlq && e instanceof QueueDoesNotExist)) throw e
|
|
116
|
+
await getOrCreateDLQ(queue, opt)
|
|
117
|
+
params = await getFailParams(queue, opt)
|
|
81
118
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
119
|
+
|
|
120
|
+
// Create our fail queue
|
|
121
|
+
const client = getSQSClient()
|
|
85
122
|
const cmd = new CreateQueueCommand(params)
|
|
86
123
|
if (opt.verbose) console.error(chalk.blue('Creating fail queue ') + fqname)
|
|
87
124
|
const data = await client.send(cmd)
|
|
@@ -92,6 +129,30 @@ export async function getOrCreateFailQueue (queue, opt) {
|
|
|
92
129
|
}
|
|
93
130
|
}
|
|
94
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Returns the parameters needed for creating a queue. If fail options
|
|
134
|
+
* are set, it makes an API call to get the fail queue's ARN.
|
|
135
|
+
*/
|
|
136
|
+
export async function getQueueParams (queue, opt) {
|
|
137
|
+
const qname = normalizeQueueName(queue, opt)
|
|
138
|
+
const fqname = normalizeFailQueueName(queue, opt)
|
|
139
|
+
const fqrl = await qrlCacheGet(fqname, opt)
|
|
140
|
+
const fqa = await getQueueAttributes(fqrl)
|
|
141
|
+
const params = {
|
|
142
|
+
Attributes: {
|
|
143
|
+
MessageRetentionPeriod: opt.messageRetentionPeriod + '',
|
|
144
|
+
RedrivePolicy: JSON.stringify({
|
|
145
|
+
deadLetterTargetArn: fqa.Attributes.QueueArn,
|
|
146
|
+
maxReceiveCount: 1
|
|
147
|
+
})
|
|
148
|
+
},
|
|
149
|
+
QueueName: qname
|
|
150
|
+
}
|
|
151
|
+
if (opt.tags) params.tags = opt.tags
|
|
152
|
+
if (opt.fifo) params.Attributes.FifoQueue = 'true'
|
|
153
|
+
return params
|
|
154
|
+
}
|
|
155
|
+
|
|
95
156
|
/**
|
|
96
157
|
* Returns a qrl for a queue that either exists or does not
|
|
97
158
|
*/
|
|
@@ -105,29 +166,25 @@ export async function getOrCreateQueue (queue, opt) {
|
|
|
105
166
|
// Anything other than queue doesn't exist gets re-thrown
|
|
106
167
|
if (!(err instanceof QueueDoesNotExist)) throw err
|
|
107
168
|
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
169
|
+
// Grab params, creating fail queue if needed
|
|
170
|
+
let params
|
|
171
|
+
try {
|
|
172
|
+
params = await getQueueParams(qname, opt)
|
|
173
|
+
} catch (e) {
|
|
174
|
+
// If fail queue doesn't exist, create it
|
|
175
|
+
if (!(e instanceof QueueDoesNotExist)) throw e
|
|
176
|
+
await getOrCreateFailQueue(qname, opt, true)
|
|
177
|
+
params = await getQueueParams(qname, opt)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
debug({ getOrCreateQueue: { qname, params } })
|
|
111
181
|
|
|
112
182
|
// Create our queue
|
|
113
183
|
const client = getSQSClient()
|
|
114
|
-
const params = {
|
|
115
|
-
Attributes: {
|
|
116
|
-
MessageRetentionPeriod: opt.messageRetentionPeriod + '',
|
|
117
|
-
RedrivePolicy: JSON.stringify({
|
|
118
|
-
deadLetterTargetArn: fqa.Attributes.QueueArn,
|
|
119
|
-
maxReceiveCount: '1'
|
|
120
|
-
})
|
|
121
|
-
},
|
|
122
|
-
QueueName: qname
|
|
123
|
-
}
|
|
124
|
-
if (opt.tags) params.tags = opt.tags
|
|
125
|
-
if (opt.fifo) params.Attributes.FifoQueue = 'true'
|
|
126
184
|
const cmd = new CreateQueueCommand(params)
|
|
127
|
-
|
|
128
|
-
if (opt.verbose) console.error(chalk.blue('Creating queue ') + qname)
|
|
185
|
+
if (opt.verbose) console.error(chalk.blue('Creating fail queue ') + qname)
|
|
129
186
|
const data = await client.send(cmd)
|
|
130
|
-
debug('createQueue returned', data)
|
|
187
|
+
debug('AWS createQueue returned', data)
|
|
131
188
|
const qrl = data.QueueUrl
|
|
132
189
|
qrlCacheSet(qname, qrl)
|
|
133
190
|
return qrl
|
|
@@ -145,17 +202,15 @@ export async function getQueueAttributes (qrl) {
|
|
|
145
202
|
return data
|
|
146
203
|
}
|
|
147
204
|
|
|
148
|
-
export function formatMessage (
|
|
149
|
-
const message = {
|
|
150
|
-
/*
|
|
151
|
-
MessageAttributes: {
|
|
152
|
-
City: { DataType: 'String', StringValue: 'Any City' },
|
|
153
|
-
Population: { DataType: 'Number', StringValue: '1250800' }
|
|
154
|
-
},
|
|
155
|
-
*/
|
|
156
|
-
MessageBody: command
|
|
157
|
-
}
|
|
205
|
+
export function formatMessage (body, id, opt, messageOptions) {
|
|
206
|
+
const message = { MessageBody: body }
|
|
158
207
|
if (typeof id !== 'undefined') message.Id = '' + id
|
|
208
|
+
if (opt.fifo) {
|
|
209
|
+
message.MessageGroupId = messageOptions?.groupId || opt?.groupId
|
|
210
|
+
}
|
|
211
|
+
addDedupParamsToMessage(message, opt, messageOptions)
|
|
212
|
+
if (opt.delay) message.DelaySeconds = opt.delay
|
|
213
|
+
if (messageOptions?.delay) message.DelaySeconds = messageOptions.delay
|
|
159
214
|
return message
|
|
160
215
|
}
|
|
161
216
|
|
|
@@ -166,14 +221,19 @@ const retryableExceptions = [
|
|
|
166
221
|
QueueDoesNotExist // Queue could temporarily not exist due to eventual consistency, let it retry
|
|
167
222
|
]
|
|
168
223
|
|
|
169
|
-
export async function sendMessage (qrl, command, opt) {
|
|
224
|
+
export async function sendMessage (qrl, command, opt, messageOptions) {
|
|
170
225
|
debug('sendMessage(', qrl, command, ')')
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
226
|
+
const uuidFunction = opt.uuidFunction || uuidV1
|
|
227
|
+
const params = {
|
|
228
|
+
QueueUrl: qrl,
|
|
229
|
+
...formatMessage(command, null, opt, messageOptions)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// See if we even have to send it
|
|
233
|
+
if (opt.externalDedup) {
|
|
234
|
+
const shouldEnqueue = await dedupShouldEnqueue(params, opt)
|
|
235
|
+
if (!shouldEnqueue) return { MessageId: uuidFunction() }
|
|
175
236
|
}
|
|
176
|
-
if (opt.delay) params.DelaySeconds = opt.delay
|
|
177
237
|
|
|
178
238
|
// Send it
|
|
179
239
|
const client = getSQSClient()
|
|
@@ -187,12 +247,15 @@ export async function sendMessage (qrl, command, opt) {
|
|
|
187
247
|
return data
|
|
188
248
|
}
|
|
189
249
|
const shouldRetry = async (result, error) => {
|
|
250
|
+
if (!error) return false
|
|
190
251
|
for (const exceptionClass of retryableExceptions) {
|
|
191
252
|
if (error instanceof exceptionClass) {
|
|
192
253
|
debug({ sendMessageRetryingBecause: { error, result } })
|
|
193
254
|
return true
|
|
194
255
|
}
|
|
195
256
|
}
|
|
257
|
+
// If we could not send it, we also need to remove our dedup flag
|
|
258
|
+
await dedupSuccessfullyProcessed(params, opt)
|
|
196
259
|
return false
|
|
197
260
|
}
|
|
198
261
|
const result = await backoff.run(send, shouldRetry)
|
|
@@ -203,25 +266,19 @@ export async function sendMessage (qrl, command, opt) {
|
|
|
203
266
|
export async function sendMessageBatch (qrl, messages, opt) {
|
|
204
267
|
debug('sendMessageBatch(', qrl, messages.map(e => Object.assign(Object.assign({}, e), { MessageBody: e.MessageBody.slice(0, 10) + '...' })), ')')
|
|
205
268
|
const params = { Entries: messages, QueueUrl: qrl }
|
|
206
|
-
const uuidFunction = opt.uuidFunction || uuidV1
|
|
207
|
-
// Add in group id if we're using fifo
|
|
208
|
-
if (opt.fifo) {
|
|
209
|
-
params.Entries = params.Entries.map(
|
|
210
|
-
message => Object.assign({
|
|
211
|
-
MessageGroupId: opt.groupIdPerMessage ? uuidFunction() : opt.groupId,
|
|
212
|
-
MessageDeduplicationId: opt.deduplicationId || uuidFunction()
|
|
213
|
-
}, message)
|
|
214
|
-
)
|
|
215
|
-
}
|
|
216
|
-
if (opt.delay) {
|
|
217
|
-
params.Entries = params.Entries.map(message =>
|
|
218
|
-
Object.assign({ DelaySeconds: opt.delay }, message))
|
|
219
|
-
}
|
|
220
269
|
if (opt.sentryDsn) {
|
|
221
270
|
addBreadcrumb({ category: 'sendMessageBatch', message: JSON.stringify({ params }), level: 'debug' })
|
|
222
271
|
}
|
|
223
272
|
debug({ params })
|
|
224
273
|
|
|
274
|
+
// See which messages we even have to send
|
|
275
|
+
if (opt.externalDedup) {
|
|
276
|
+
const promises = params.Entries.map(async m => ({ m, shouldEnqueue: await dedupShouldEnqueue(m, opt) }))
|
|
277
|
+
const results = await Promise.all(promises)
|
|
278
|
+
params.Entries = results.filter(({ shouldEnqueue }) => shouldEnqueue)
|
|
279
|
+
if (!params.Entries.length) return
|
|
280
|
+
}
|
|
281
|
+
|
|
225
282
|
// Send them
|
|
226
283
|
const client = getSQSClient()
|
|
227
284
|
const cmd = new SendMessageBatchCommand(params)
|
|
@@ -320,8 +377,8 @@ export async function flushMessages (qrl, opt, sendBuffer) {
|
|
|
320
377
|
// Automaticaly flushes if queue has >= 10 messages.
|
|
321
378
|
// Returns number of messages flushed.
|
|
322
379
|
//
|
|
323
|
-
export async function addMessage (qrl, command, messageIndex, opt, sendBuffer) {
|
|
324
|
-
const message = formatMessage(command, messageIndex)
|
|
380
|
+
export async function addMessage (qrl, command, messageIndex, opt, sendBuffer, messageOptions) {
|
|
381
|
+
const message = formatMessage(command, messageIndex, opt, messageOptions)
|
|
325
382
|
sendBuffer[qrl] = sendBuffer[qrl] || []
|
|
326
383
|
sendBuffer[qrl].push(message)
|
|
327
384
|
debug({ location: 'addMessage', sendBuffer })
|
|
@@ -338,8 +395,16 @@ export async function addMessage (qrl, command, messageIndex, opt, sendBuffer) {
|
|
|
338
395
|
export async function enqueue (queue, command, options) {
|
|
339
396
|
debug('enqueue(', { queue, command }, ')')
|
|
340
397
|
const opt = getOptionsWithDefaults(options)
|
|
341
|
-
|
|
342
|
-
|
|
398
|
+
if (opt.sentryDsn) {
|
|
399
|
+
setExtra({ qdoneOperation: 'enqueue', args: { queue, command, opt } })
|
|
400
|
+
}
|
|
401
|
+
try {
|
|
402
|
+
const qrl = await getOrCreateQueue(queue, opt)
|
|
403
|
+
return sendMessage(qrl, command, opt)
|
|
404
|
+
} catch (e) {
|
|
405
|
+
console.log(e)
|
|
406
|
+
throw e
|
|
407
|
+
}
|
|
343
408
|
}
|
|
344
409
|
|
|
345
410
|
//
|
|
@@ -349,43 +414,50 @@ export async function enqueue (queue, command, options) {
|
|
|
349
414
|
export async function enqueueBatch (pairs, options) {
|
|
350
415
|
debug('enqueueBatch(', pairs, ')')
|
|
351
416
|
const opt = getOptionsWithDefaults(options)
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
// queues are created prior to going through our flush logic
|
|
355
|
-
const normalizedPairs = pairs.map(({ queue, command }) => ({
|
|
356
|
-
qname: normalizeQueueName(queue, opt),
|
|
357
|
-
command
|
|
358
|
-
}))
|
|
359
|
-
const uniqueQnames = new Set(normalizedPairs.map(p => p.qname))
|
|
360
|
-
|
|
361
|
-
// Prefetch qrls / create queues in parallel
|
|
362
|
-
const createPromises = []
|
|
363
|
-
for (const qname of uniqueQnames) {
|
|
364
|
-
createPromises.push(getOrCreateQueue(qname, opt))
|
|
365
|
-
}
|
|
366
|
-
await Promise.all(createPromises)
|
|
367
|
-
|
|
368
|
-
// After we've prefetched, all qrls are in cache
|
|
369
|
-
// so go back through the list of pairs and fire off messages
|
|
370
|
-
requestCount = 0
|
|
371
|
-
const sendBuffer = {}
|
|
372
|
-
let messageIndex = 0
|
|
373
|
-
let initialFlushTotal = 0
|
|
374
|
-
for (const { qname, command } of normalizedPairs) {
|
|
375
|
-
const qrl = await getOrCreateQueue(qname, opt)
|
|
376
|
-
initialFlushTotal += await addMessage(qrl, command, messageIndex++, opt, sendBuffer)
|
|
417
|
+
if (opt.sentryDsn) {
|
|
418
|
+
setExtra({ qdoneOperation: 'enqueueBatch', args: { pairs, opt } })
|
|
377
419
|
}
|
|
420
|
+
try {
|
|
421
|
+
// Find unique queues so we can pre-fetch qrls. We do this so that all
|
|
422
|
+
// queues are created prior to going through our flush logic
|
|
423
|
+
const normalizedPairs = pairs.map(({ queue, command, messageOptions }) => ({
|
|
424
|
+
qname: normalizeQueueName(queue, opt),
|
|
425
|
+
command,
|
|
426
|
+
messageOptions: validateMessageOptions(messageOptions)
|
|
427
|
+
}))
|
|
428
|
+
const uniqueQnames = new Set(normalizedPairs.map(p => p.qname))
|
|
378
429
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
430
|
+
// Prefetch qrls / create queues in parallel
|
|
431
|
+
const createPromises = []
|
|
432
|
+
for (const qname of uniqueQnames) {
|
|
433
|
+
createPromises.push(getOrCreateQueue(qname, opt))
|
|
434
|
+
}
|
|
435
|
+
await Promise.all(createPromises)
|
|
436
|
+
// After we've prefetched, all qrls are in cache
|
|
437
|
+
// so go back through the list of pairs and fire off messages
|
|
438
|
+
requestCount = 0
|
|
439
|
+
const sendBuffer = {}
|
|
440
|
+
let messageIndex = 0
|
|
441
|
+
let initialFlushTotal = 0
|
|
442
|
+
for (const { qname, command, messageOptions } of normalizedPairs) {
|
|
443
|
+
const qrl = await getOrCreateQueue(qname, opt)
|
|
444
|
+
initialFlushTotal += await addMessage(qrl, command, messageIndex++, opt, sendBuffer, messageOptions)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// And flush any remaining messages
|
|
448
|
+
const extraFlushPromises = []
|
|
449
|
+
for (const qrl in sendBuffer) {
|
|
450
|
+
extraFlushPromises.push(flushMessages(qrl, opt, sendBuffer))
|
|
451
|
+
}
|
|
452
|
+
const extraFlushCounts = await Promise.all(extraFlushPromises)
|
|
453
|
+
const extraFlushTotal = extraFlushCounts.reduce((a, b) => a + b, 0)
|
|
454
|
+
const totalFlushed = initialFlushTotal + extraFlushTotal
|
|
455
|
+
debug({ initialFlushTotal, extraFlushTotal, totalFlushed })
|
|
456
|
+
return totalFlushed
|
|
457
|
+
} catch (e) {
|
|
458
|
+
console.log(e)
|
|
459
|
+
throw e
|
|
383
460
|
}
|
|
384
|
-
const extraFlushCounts = await Promise.all(extraFlushPromises)
|
|
385
|
-
const extraFlushTotal = extraFlushCounts.reduce((a, b) => a + b, 0)
|
|
386
|
-
const totalFlushed = initialFlushTotal + extraFlushTotal
|
|
387
|
-
debug({ initialFlushTotal, extraFlushTotal, totalFlushed })
|
|
388
|
-
return totalFlushed
|
|
389
461
|
}
|
|
390
462
|
|
|
391
463
|
debug('loaded')
|
package/src/qrlCache.js
CHANGED
|
@@ -66,7 +66,7 @@ export async function qrlCacheGet (qname) {
|
|
|
66
66
|
// debug({ cmd })
|
|
67
67
|
const result = await client.send(cmd)
|
|
68
68
|
// debug('result', result)
|
|
69
|
-
|
|
69
|
+
if (!result) throw new QueueDoesNotExist(qname)
|
|
70
70
|
const { QueueUrl: qrl } = result
|
|
71
71
|
// debug('getQueueUrl returned', data)
|
|
72
72
|
qcache.set(qname, qrl)
|
|
@@ -8,6 +8,7 @@ import { ChangeMessageVisibilityBatchCommand, DeleteMessageBatchCommand } from '
|
|
|
8
8
|
import chalk from 'chalk'
|
|
9
9
|
import Debug from 'debug'
|
|
10
10
|
|
|
11
|
+
import { dedupSuccessfullyProcessed } from '../dedup.js'
|
|
11
12
|
import { getSQSClient } from '../sqs.js'
|
|
12
13
|
|
|
13
14
|
const debug = Debug('qdone:jobExecutor')
|
|
@@ -221,6 +222,10 @@ export class JobExecutor {
|
|
|
221
222
|
}
|
|
222
223
|
}
|
|
223
224
|
debug('DeleteMessageBatch returned', result)
|
|
225
|
+
|
|
226
|
+
// Mark batch as processed for dedup
|
|
227
|
+
await Promise.all(entries.map(e => dedupSuccessfullyProcessed(this.jobsByMessageId[e.Id], this.opt)))
|
|
228
|
+
|
|
224
229
|
// TODO Sentry
|
|
225
230
|
}
|
|
226
231
|
}
|
package/src/worker.js
CHANGED
|
@@ -13,6 +13,7 @@ import treeKill from 'tree-kill'
|
|
|
13
13
|
import chalk from 'chalk'
|
|
14
14
|
import Debug from 'debug'
|
|
15
15
|
|
|
16
|
+
import { dedupSuccessfullyProcessed } from './dedup.js'
|
|
16
17
|
import { normalizeQueueName, getQnameUrlPairs } from './qrlCache.js'
|
|
17
18
|
import { getOptionsWithDefaults } from './defaults.js'
|
|
18
19
|
import { cheapIdleCheck } from './idleQueues.js'
|
|
@@ -129,10 +130,15 @@ export async function executeJob (job, qname, qrl, opt) {
|
|
|
129
130
|
QueueUrl: qrl,
|
|
130
131
|
ReceiptHandle: job.ReceiptHandle
|
|
131
132
|
}))
|
|
133
|
+
|
|
132
134
|
if (opt.verbose) {
|
|
133
135
|
console.error(chalk.blue(' done'))
|
|
134
136
|
console.error()
|
|
135
137
|
}
|
|
138
|
+
|
|
139
|
+
// Let dedup system know we processed it
|
|
140
|
+
await dedupSuccessfullyProcessed(job, opt)
|
|
141
|
+
|
|
136
142
|
return { noJobs: 0, jobsSucceeded: 1, jobsFailed: 0 }
|
|
137
143
|
} catch (err) {
|
|
138
144
|
// Fail path for job execution
|