qdone 2.0.30-alpha → 2.0.32-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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qdone",
3
- "version": "2.0.30-alpha",
3
+ "version": "2.0.32-alpha",
4
4
  "description": "Language agnostic job queue for SQS",
5
5
  "type": "module",
6
6
  "main": "./index.js",
package/src/consumer.js CHANGED
@@ -119,7 +119,7 @@ export async function processMessages (queues, callback, options) {
119
119
 
120
120
  while (!shutdownRequested) { // eslint-disable-line
121
121
  // Figure out how we are running
122
- const allowedJobs = Math.max(0, opt.maxConcurrentJobs - jobExecutor.activeJobCount() - maxReturnCount)
122
+ const allowedJobs = Math.max(0, opt.maxConcurrentJobs - jobExecutor.runningJobCount() - maxReturnCount)
123
123
 
124
124
  // Latency
125
125
  const maxLatency = 100
@@ -147,7 +147,8 @@ export async function processMessages (queues, callback, options) {
147
147
  // console.error({ maxConcurrentJobs: opt.maxConcurrentJobs, jobCount: jobExecutor.activeJobCount(), allowedJobs, maxLatency, latencyFactor, freememFactor, loadFactor, overallFactor, targetJobs, activeQrls })
148
148
  }
149
149
  for (const { qname, qrl } of queueManager.getPairs()) {
150
- // debug({ evaluating: { qname, qrl, jobsLeft, activeQrlsHasQrl: activeQrls.has(qrl) } })
150
+ // const qcount = jobExecutor.runningJobCountForQueue(qname)
151
+ // console.log({ evaluating: { qname, qrl, qcount, jobsLeft, activeQrlsHasQrl: activeQrls.has(qrl) } })
151
152
  if (jobsLeft <= 0 || activeQrls.has(qrl)) continue
152
153
  const maxMessages = Math.min(10, jobsLeft)
153
154
  listen(qname, qrl, maxMessages)
@@ -19,6 +19,7 @@ export class JobExecutor {
19
19
  this.opt = opt
20
20
  this.jobs = []
21
21
  this.jobsByMessageId = {}
22
+ this.jobsByQueue = new Map()
22
23
  this.stats = {
23
24
  activeJobs: 0,
24
25
  waitingJobs: 0,
@@ -40,14 +41,30 @@ export class JobExecutor {
40
41
  if (this.opt.verbose) {
41
42
  console.error(chalk.blue('Shutting down jobExecutor'))
42
43
  }
43
- await this.maintainPromise
44
- await this.maintainVisibility()
44
+ while (this.stats.activeJobs > 0) {
45
+ await this.maintainPromise
46
+ await this.maintainVisibility()
47
+ }
45
48
  }
46
49
 
47
50
  activeJobCount () {
48
51
  return this.stats.activeJobs
49
52
  }
50
53
 
54
+ runningJobCount () {
55
+ return this.stats.runningJobs
56
+ }
57
+
58
+ /**
59
+ * Returns the number of jobs running in a queue.
60
+ */
61
+ runningJobCountForQueue (qname) {
62
+ const jobs = this.jobsByQueue.get(qname) || new Set()
63
+ let runningCount = 0
64
+ for (const job of jobs.values()) runningCount += job.status === 'running'
65
+ return runningCount
66
+ }
67
+
51
68
  /**
52
69
  * Changes message visibility on all running jobs using as few calls as possible.
53
70
  */
@@ -109,7 +126,16 @@ export class JobExecutor {
109
126
 
110
127
  if (this.opt.verbose) {
111
128
  console.error(chalk.blue('Stats: '), { stats: this.stats, jobStatuses })
112
- console.error(chalk.blue('Running: '), this.jobs.filter(j => j.status === 'processing').map(({ qname, message }) => ({ qname, payload: message.Body })))
129
+ console.error(chalk.blue('Jobs: '))
130
+ for (const [qname, jobs] of this.jobsByQueue.entries()) {
131
+ if (jobs.size) {
132
+ console.error(chalk.blue(' queue:'), qname)
133
+ for (const job of jobs) if (job.status === 'running') console.error(chalk.green(' running: '), job.payload)
134
+ for (const job of jobs) if (job.status === 'waiting') console.error(chalk.gold(' waiting:'), job.payload)
135
+ for (const job of jobs) if (job.status === 'complete' || job.status === 'deleting') console.error(chalk.blue(' complete:'), job.payload)
136
+ for (const job of jobs) if (job.status === 'failed') console.error(chalk.red(' failed:'), job.payload)
137
+ }
138
+ }
113
139
  }
114
140
 
115
141
  // Extend in batches for each queue
@@ -203,7 +229,9 @@ export class JobExecutor {
203
229
  this.jobs = this.jobs.filter(job => {
204
230
  if (job.status === 'deleting' || job.status === 'failed') {
205
231
  debug('removed', job.message.MessageId)
232
+ // Accounting
206
233
  delete this.jobsByMessageId[job.message.MessageId]
234
+ this.jobsByQueue.get(job.qname).delete(job)
207
235
  return false
208
236
  } else {
209
237
  return true
@@ -240,8 +268,14 @@ export class JobExecutor {
240
268
  throw e
241
269
  }
242
270
 
271
+ // Accounting
243
272
  this.jobs.push(job)
244
273
  this.jobsByMessageId[job.message.MessageId] = job
274
+
275
+ // Track all jobs for each queue
276
+ if (!this.jobsByQueue.has(job.qname)) this.jobsByQueue.set(job.qname, new Set())
277
+ this.jobsByQueue.get(job.qname).add(job)
278
+
245
279
  this.stats.activeJobs++
246
280
  this.stats.waitingJobs++
247
281
  if (this.opt.verbose) {
@@ -332,13 +366,10 @@ export class JobExecutor {
332
366
  // Begin executing
333
367
  for (const [job, i] of jobs.map((job, i) => [job, i])) {
334
368
  // Figure out if the next job needs to happen in serial, otherwise we can parallel execute
335
- // const job = jobs[i]
336
369
  const nextJob = jobs[i + 1]
337
- const nextJobIsSerial =
338
- isFifo && nextJob &&
339
- job.message?.Attributes?.GroupId === nextJob.message?.Attributes?.GroupId
370
+ const nextJobIsSerial = isFifo && nextJob && job.message?.Attributes?.GroupId === nextJob.message?.Attributes?.GroupId
340
371
 
341
- console.log({ i, nextJobAtt: nextJob.message.Attributes, nextJobIsSerial })
372
+ // console.log({ i, nextJobAtt: nextJob?.message?.Attributes, nextJobIsSerial })
342
373
  // Execute serial or parallel
343
374
  if (nextJobIsSerial) await this.runJob(job)
344
375
  else this.runJob(job)