qdone 2.0.26-alpha → 2.0.28-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commonjs/src/consumer.js +17 -13
- package/commonjs/src/scheduler/jobExecutor.js +53 -34
- package/commonjs/src/scheduler/queueManager.js +10 -7
- package/npm-shrinkwrap.json +15999 -0
- package/package.json +1 -1
- package/src/consumer.js +17 -11
- package/src/scheduler/jobExecutor.js +33 -18
- package/src/scheduler/queueManager.js +10 -8
package/package.json
CHANGED
package/src/consumer.js
CHANGED
|
@@ -86,18 +86,24 @@ export async function processMessages (queues, callback, options) {
|
|
|
86
86
|
const activeQrls = new Set()
|
|
87
87
|
let maxReturnCount = 0
|
|
88
88
|
const listen = async (qname, qrl, maxMessages) => {
|
|
89
|
+
if (opt.verbose) {
|
|
90
|
+
console.error(chalk.blue('Listening on: '), qname)
|
|
91
|
+
}
|
|
89
92
|
activeQrls.add(qrl)
|
|
90
93
|
maxReturnCount += maxMessages
|
|
91
94
|
try {
|
|
92
95
|
const messages = await getMessages(qrl, opt, maxMessages)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
|
|
97
|
+
if (!shutdownRequested) {
|
|
98
|
+
if (messages.length) {
|
|
99
|
+
for (const message of messages) {
|
|
100
|
+
jobExecutor.executeJob(message, callback, qname, qrl, () => queueManager.updateIcehouse(qrl, true))
|
|
101
|
+
}
|
|
102
|
+
queueManager.updateIcehouse(qrl, false)
|
|
103
|
+
} else {
|
|
104
|
+
// If we didn't get any, update the icehouse so we can back off
|
|
105
|
+
queueManager.updateIcehouse(qrl, true)
|
|
96
106
|
}
|
|
97
|
-
queueManager.updateIcehouse(qrl, false)
|
|
98
|
-
} else {
|
|
99
|
-
// If we didn't get any, update the icehouse so we can back off
|
|
100
|
-
queueManager.updateIcehouse(qrl, true)
|
|
101
107
|
}
|
|
102
108
|
|
|
103
109
|
// Max job accounting
|
|
@@ -138,16 +144,16 @@ export async function processMessages (queues, callback, options) {
|
|
|
138
144
|
const overallFactor = Math.min(latencyFactor, freememFactor, loadFactor)
|
|
139
145
|
const targetJobs = Math.round(allowedJobs * overallFactor)
|
|
140
146
|
let jobsLeft = targetJobs
|
|
141
|
-
|
|
147
|
+
|
|
148
|
+
if (opt.verbose) {
|
|
149
|
+
console.error({ jobCount: jobExecutor.activeJobCount(), freeMemory, totalMemory, freememThreshold, remainingMemory, memoryThreshold, maxReturnCount, allowedJobs, maxLatency, latency, latencyFactor, freememFactor, oneMinuteLoad, loadPerCore, loadFactor, overallFactor, targetJobs, activeQrls })
|
|
150
|
+
}
|
|
142
151
|
for (const { qname, qrl } of queueManager.getPairs()) {
|
|
143
152
|
// debug({ evaluating: { qname, qrl, jobsLeft, activeQrlsHasQrl: activeQrls.has(qrl) } })
|
|
144
153
|
if (jobsLeft <= 0 || activeQrls.has(qrl)) continue
|
|
145
154
|
const maxMessages = Math.min(10, jobsLeft)
|
|
146
155
|
listen(qname, qrl, maxMessages)
|
|
147
156
|
jobsLeft -= maxMessages
|
|
148
|
-
if (opt.verbose) {
|
|
149
|
-
console.error(chalk.blue('Listening on: '), qname)
|
|
150
|
-
}
|
|
151
157
|
// debug({ listenedTo: { qname, maxMessages, jobsLeft } })
|
|
152
158
|
}
|
|
153
159
|
await delay(1000)
|
|
@@ -35,6 +35,9 @@ export class JobExecutor {
|
|
|
35
35
|
this.shutdownRequested = true
|
|
36
36
|
// Trigger a maintenance run right away in case it speeds us up
|
|
37
37
|
clearTimeout(this.maintainVisibilityTimeout)
|
|
38
|
+
if (this.opt.verbose) {
|
|
39
|
+
console.error(chalk.blue('Shutting down jobExecutor'))
|
|
40
|
+
}
|
|
38
41
|
await this.maintainPromise
|
|
39
42
|
await this.maintainVisibility()
|
|
40
43
|
}
|
|
@@ -47,7 +50,21 @@ export class JobExecutor {
|
|
|
47
50
|
* Changes message visibility on all running jobs using as few calls as possible.
|
|
48
51
|
*/
|
|
49
52
|
async maintainVisibility () {
|
|
53
|
+
// Bail if we are shutting down
|
|
54
|
+
if (this.shutdownRequested && this.stats.activeJobs === 0 && this.jobs.length === 0) {
|
|
55
|
+
if (this.opt.verbose) {
|
|
56
|
+
console.error(chalk.blue('All workers done, finishing shutdown of jobExecutor'))
|
|
57
|
+
}
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Reset our timeout
|
|
50
62
|
clearTimeout(this.maintainVisibilityTimeout)
|
|
63
|
+
const nextCheckInMs = this.shutdownRequested ? 1000 : 10 * 1000
|
|
64
|
+
this.maintainVisibilityTimeout = setTimeout(() => {
|
|
65
|
+
this.maintainPromise = this.maintainVisibility()
|
|
66
|
+
}, nextCheckInMs)
|
|
67
|
+
|
|
51
68
|
// debug('maintainVisibility', this.jobs)
|
|
52
69
|
const start = new Date()
|
|
53
70
|
const jobsToExtendByQrl = {}
|
|
@@ -84,7 +101,7 @@ export class JobExecutor {
|
|
|
84
101
|
const secondsUntilMax = Math.max(1, maxJobSeconds - jobRunTime)
|
|
85
102
|
// const secondsUntilKill = Math.max(1, this.opt.killAfter - jobRunTime)
|
|
86
103
|
job.visibilityTimeout = Math.min(doubled, secondsUntilMax) //, secondsUntilKill)
|
|
87
|
-
job.extendAtSecond = Math.round(jobRunTime + job.visibilityTimeout) // this is what we use next time
|
|
104
|
+
job.extendAtSecond = Math.round(jobRunTime + job.visibilityTimeout / 2) // this is what we use next time
|
|
88
105
|
debug({ doubled, secondsUntilMax, job })
|
|
89
106
|
}
|
|
90
107
|
}
|
|
@@ -102,7 +119,7 @@ export class JobExecutor {
|
|
|
102
119
|
while (messageId++ < 10 && jobsToExtend.length) {
|
|
103
120
|
const job = jobsToExtend.shift()
|
|
104
121
|
const entry = {
|
|
105
|
-
Id:
|
|
122
|
+
Id: job.message.MessageId,
|
|
106
123
|
ReceiptHandle: job.message.ReceiptHandle,
|
|
107
124
|
VisibilityTimeout: job.visibilityTimeout
|
|
108
125
|
}
|
|
@@ -116,6 +133,12 @@ export class JobExecutor {
|
|
|
116
133
|
const result = await getSQSClient().send(new ChangeMessageVisibilityBatchCommand(input))
|
|
117
134
|
debug('ChangeMessageVisibilityBatch returned', result)
|
|
118
135
|
this.stats.sqsCalls++
|
|
136
|
+
if (result.Failed) {
|
|
137
|
+
console.error('FAILED_MESSAGES', result.Failed)
|
|
138
|
+
for (const failed of result.Failed) {
|
|
139
|
+
console.error('FAILED_TO_EXTEND_JOB', this.jobsByMessageId[failed.Id])
|
|
140
|
+
}
|
|
141
|
+
}
|
|
119
142
|
if (result.Successful) {
|
|
120
143
|
const count = result.Successful.length || 0
|
|
121
144
|
this.stats.timeoutsExtended += count
|
|
@@ -139,7 +162,7 @@ export class JobExecutor {
|
|
|
139
162
|
while (messageId++ < 10 && jobsToDelete.length) {
|
|
140
163
|
const job = jobsToDelete.shift()
|
|
141
164
|
const entry = {
|
|
142
|
-
Id:
|
|
165
|
+
Id: job.message.MessageId,
|
|
143
166
|
ReceiptHandle: job.message.ReceiptHandle,
|
|
144
167
|
VisibilityTimeout: job.visibilityTimeout
|
|
145
168
|
}
|
|
@@ -152,6 +175,12 @@ export class JobExecutor {
|
|
|
152
175
|
debug({ DeleteMessageBatch: input })
|
|
153
176
|
const result = await getSQSClient().send(new DeleteMessageBatchCommand(input))
|
|
154
177
|
this.stats.sqsCalls++
|
|
178
|
+
if (result.Failed) {
|
|
179
|
+
console.error('FAILED_MESSAGES', result.Failed)
|
|
180
|
+
for (const failed of result.Failed) {
|
|
181
|
+
console.error('FAILED_TO_DELETE_JOB', this.jobsByMessageId[failed.Id])
|
|
182
|
+
}
|
|
183
|
+
}
|
|
155
184
|
if (result.Successful) {
|
|
156
185
|
const count = result.Successful.length || 0
|
|
157
186
|
this.stats.jobsDeleted += count
|
|
@@ -176,24 +205,10 @@ export class JobExecutor {
|
|
|
176
205
|
return true
|
|
177
206
|
}
|
|
178
207
|
})
|
|
179
|
-
|
|
180
|
-
// Bail if we are shutting down
|
|
181
|
-
if (this.shutdownRequested && this.stats.activeJobs === 0 && this.jobs.length === 0) return
|
|
182
|
-
|
|
183
|
-
// Check later, but count the time we spent. Make sure we check at least
|
|
184
|
-
// every period seconds.
|
|
185
|
-
const msElapsed = new Date() - start
|
|
186
|
-
const msPeriod = this.shutdownRequested ? 1 * 1000 : 10 * 1000
|
|
187
|
-
const msLeft = Math.max(0, msPeriod - msElapsed)
|
|
188
|
-
const msMin = this.shutdownRequested ? 1000 : 0
|
|
189
|
-
const nextCheckInMs = Math.max(msMin, msLeft)
|
|
190
|
-
debug({ msElapsed, msPeriod, msLeft, msMin, nextCheckInMs })
|
|
191
|
-
this.maintainVisibilityTimeout = setTimeout(() => {
|
|
192
|
-
this.maintainPromise = this.maintainVisibility()
|
|
193
|
-
}, nextCheckInMs)
|
|
194
208
|
}
|
|
195
209
|
|
|
196
210
|
async executeJob (message, callback, qname, qrl, failedCallback) {
|
|
211
|
+
if (this.shutdownRequested) throw new Error('jobExecutor is shutting down so cannot execute new job')
|
|
197
212
|
// Create job entry and track it
|
|
198
213
|
const payload = this.opt.json ? JSON.parse(message.Body) : message.Body
|
|
199
214
|
const visibilityTimeout = 60
|
|
@@ -69,6 +69,12 @@ export class QueueManager {
|
|
|
69
69
|
async resolveQueues () {
|
|
70
70
|
clearTimeout(this.resolveTimeout)
|
|
71
71
|
if (this.shutdownRequested) return
|
|
72
|
+
this.resolveTimeout = setTimeout(() => {
|
|
73
|
+
this.resolvePromise = this.resolveQueues()
|
|
74
|
+
}, this.resolveSeconds * 1000)
|
|
75
|
+
if (this.opt.verbose) {
|
|
76
|
+
console.error(chalk.blue('Will resolve queues again in ' + this.resolveSeconds + ' seconds'))
|
|
77
|
+
}
|
|
72
78
|
|
|
73
79
|
// Start processing
|
|
74
80
|
const qnames = this.queues.map(queue => normalizeQueueName(queue, this.opt))
|
|
@@ -120,16 +126,9 @@ export class QueueManager {
|
|
|
120
126
|
|
|
121
127
|
// Finished resolving
|
|
122
128
|
if (this.opt.verbose) {
|
|
123
|
-
console.error(chalk.blue('
|
|
129
|
+
console.error(chalk.blue('Done resolving'))
|
|
124
130
|
console.error()
|
|
125
131
|
}
|
|
126
|
-
|
|
127
|
-
if (this.opt.verbose) {
|
|
128
|
-
console.error(chalk.blue('Will resolve queues again in ' + this.resolveSeconds + ' seconds'))
|
|
129
|
-
}
|
|
130
|
-
this.resolveTimeout = setTimeout(() => {
|
|
131
|
-
this.resolvePromise = this.resolveQueues()
|
|
132
|
-
}, this.resolveSeconds * 1000)
|
|
133
132
|
}
|
|
134
133
|
|
|
135
134
|
// Return the next queue in the lineup
|
|
@@ -147,6 +146,9 @@ export class QueueManager {
|
|
|
147
146
|
async shutdown () {
|
|
148
147
|
this.shutdownRequested = true
|
|
149
148
|
clearTimeout(this.resolveTimeout)
|
|
149
|
+
if (this.opt.verbose) {
|
|
150
|
+
console.error(chalk.blue('Waiting for queues to resolve'))
|
|
151
|
+
}
|
|
150
152
|
await this.resolvePromise
|
|
151
153
|
}
|
|
152
154
|
}
|