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.
@@ -117,7 +117,7 @@ async function processMessages(queues, callback, options) {
117
117
  };
118
118
  while (!shutdownRequested) { // eslint-disable-line
119
119
  // Figure out how we are running
120
- const allowedJobs = Math.max(0, opt.maxConcurrentJobs - jobExecutor.activeJobCount() - maxReturnCount);
120
+ const allowedJobs = Math.max(0, opt.maxConcurrentJobs - jobExecutor.runningJobCount() - maxReturnCount);
121
121
  // Latency
122
122
  const maxLatency = 100;
123
123
  const latency = systemMonitor.getLatency() || 10;
@@ -140,7 +140,8 @@ async function processMessages(queues, callback, options) {
140
140
  // console.error({ maxConcurrentJobs: opt.maxConcurrentJobs, jobCount: jobExecutor.activeJobCount(), allowedJobs, maxLatency, latencyFactor, freememFactor, loadFactor, overallFactor, targetJobs, activeQrls })
141
141
  }
142
142
  for (const { qname, qrl } of queueManager.getPairs()) {
143
- // debug({ evaluating: { qname, qrl, jobsLeft, activeQrlsHasQrl: activeQrls.has(qrl) } })
143
+ // const qcount = jobExecutor.runningJobCountForQueue(qname)
144
+ // console.log({ evaluating: { qname, qrl, qcount, jobsLeft, activeQrlsHasQrl: activeQrls.has(qrl) } })
144
145
  if (jobsLeft <= 0 || activeQrls.has(qrl))
145
146
  continue;
146
147
  const maxMessages = Math.min(10, jobsLeft);
@@ -19,6 +19,7 @@ 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,
@@ -39,12 +40,27 @@ class JobExecutor {
39
40
  if (this.opt.verbose) {
40
41
  console.error(chalk_1.default.blue('Shutting down jobExecutor'));
41
42
  }
42
- await this.maintainPromise;
43
- await this.maintainVisibility();
43
+ while (this.stats.activeJobs > 0) {
44
+ await this.maintainPromise;
45
+ await this.maintainVisibility();
46
+ }
44
47
  }
45
48
  activeJobCount() {
46
49
  return this.stats.activeJobs;
47
50
  }
51
+ runningJobCount() {
52
+ return this.stats.runningJobs;
53
+ }
54
+ /**
55
+ * Returns the number of jobs running in a queue.
56
+ */
57
+ runningJobCountForQueue(qname) {
58
+ const jobs = this.jobsByQueue.get(qname) || new Set();
59
+ let runningCount = 0;
60
+ for (const job of jobs.values())
61
+ runningCount += job.status === 'running';
62
+ return runningCount;
63
+ }
48
64
  /**
49
65
  * Changes message visibility on all running jobs using as few calls as possible.
50
66
  */
@@ -103,7 +119,24 @@ class JobExecutor {
103
119
  }
104
120
  if (this.opt.verbose) {
105
121
  console.error(chalk_1.default.blue('Stats: '), { stats: this.stats, jobStatuses });
106
- console.error(chalk_1.default.blue('Running: '), this.jobs.filter(j => j.status === 'processing').map(({ qname, message }) => ({ qname, payload: message.Body })));
122
+ console.error(chalk_1.default.blue('Jobs: '));
123
+ for (const [qname, jobs] of this.jobsByQueue.entries()) {
124
+ if (jobs.size) {
125
+ console.error(chalk_1.default.blue(' queue:'), qname);
126
+ for (const job of jobs)
127
+ if (job.status === 'running')
128
+ console.error(chalk_1.default.green(' running: '), job.payload);
129
+ for (const job of jobs)
130
+ if (job.status === 'waiting')
131
+ console.error(chalk_1.default.gold(' waiting:'), job.payload);
132
+ for (const job of jobs)
133
+ if (job.status === 'complete' || job.status === 'deleting')
134
+ console.error(chalk_1.default.blue(' complete:'), job.payload);
135
+ for (const job of jobs)
136
+ if (job.status === 'failed')
137
+ console.error(chalk_1.default.red(' failed:'), job.payload);
138
+ }
139
+ }
107
140
  }
108
141
  // Extend in batches for each queue
109
142
  for (const qrl in jobsToExtendByQrl) {
@@ -194,7 +227,9 @@ class JobExecutor {
194
227
  this.jobs = this.jobs.filter(job => {
195
228
  if (job.status === 'deleting' || job.status === 'failed') {
196
229
  debug('removed', job.message.MessageId);
230
+ // Accounting
197
231
  delete this.jobsByMessageId[job.message.MessageId];
232
+ this.jobsByQueue.get(job.qname).delete(job);
198
233
  return false;
199
234
  }
200
235
  else {
@@ -229,8 +264,13 @@ class JobExecutor {
229
264
  // TODO: sentry breadcrumb
230
265
  throw e;
231
266
  }
267
+ // Accounting
232
268
  this.jobs.push(job);
233
269
  this.jobsByMessageId[job.message.MessageId] = job;
270
+ // Track all jobs for each queue
271
+ if (!this.jobsByQueue.has(job.qname))
272
+ this.jobsByQueue.set(job.qname, new Set());
273
+ this.jobsByQueue.get(job.qname).add(job);
234
274
  this.stats.activeJobs++;
235
275
  this.stats.waitingJobs++;
236
276
  if (this.opt.verbose) {
@@ -321,11 +361,9 @@ class JobExecutor {
321
361
  // Begin executing
322
362
  for (const [job, i] of jobs.map((job, i) => [job, i])) {
323
363
  // Figure out if the next job needs to happen in serial, otherwise we can parallel execute
324
- // const job = jobs[i]
325
364
  const nextJob = jobs[i + 1];
326
- const nextJobIsSerial = isFifo && nextJob &&
327
- job.message?.Attributes?.GroupId === nextJob.message?.Attributes?.GroupId;
328
- console.log({ i, nextJobAtt: nextJob.message.Attributes, nextJobIsSerial });
365
+ const nextJobIsSerial = isFifo && nextJob && job.message?.Attributes?.GroupId === nextJob.message?.Attributes?.GroupId;
366
+ // console.log({ i, nextJobAtt: nextJob?.message?.Attributes, nextJobIsSerial })
329
367
  // Execute serial or parallel
330
368
  if (nextJobIsSerial)
331
369
  await this.runJob(job);