qdone 2.0.8-alpha → 2.0.10-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/index.js +1 -2
- package/commonjs/src/consumer.js +80 -386
- package/commonjs/src/scheduler/jobExecutor.js +321 -0
- package/commonjs/src/scheduler/queueManager.js +145 -0
- package/commonjs/src/scheduler/systemMonitor.js +65 -0
- package/index.js +1 -1
- package/package.json +1 -1
- package/src/consumer.js +55 -292
- package/src/scheduler/jobExecutor.js +242 -0
- package/src/scheduler/queueManager.js +88 -0
- package/src/scheduler/systemMonitor.js +58 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component to manange what queues are being listened to and in what order.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import chalk from 'chalk'
|
|
6
|
+
import Debug from 'debug'
|
|
7
|
+
|
|
8
|
+
import { normalizeQueueName, getQnameUrlPairs } from '../qrlCache.js'
|
|
9
|
+
import { cheapIdleCheck } from '../idleQueues.js'
|
|
10
|
+
import { getSQSClient } from '../sqs.js'
|
|
11
|
+
|
|
12
|
+
const debug = Debug('qdone:queueManager')
|
|
13
|
+
|
|
14
|
+
export class QueueManager {
|
|
15
|
+
constructor (opt, queues, resolveSeconds = 10) {
|
|
16
|
+
this.opt = opt
|
|
17
|
+
this.queues = queues
|
|
18
|
+
this.resolveSeconds = resolveSeconds
|
|
19
|
+
this.selectedPairs = []
|
|
20
|
+
this.resolveTimeout = undefined
|
|
21
|
+
this.shutdownRequested = false
|
|
22
|
+
this.resolveQueues()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async resolveQueues () {
|
|
26
|
+
if (this.shutdownRequested) return
|
|
27
|
+
|
|
28
|
+
// Start processing
|
|
29
|
+
if (this.opt.verbose) console.error(chalk.blue('Resolving queues: ') + this.queues.join(' '))
|
|
30
|
+
const qnames = this.queues.map(queue => normalizeQueueName(queue, this.opt))
|
|
31
|
+
const pairs = await getQnameUrlPairs(qnames, this.opt)
|
|
32
|
+
|
|
33
|
+
if (this.shutdownRequested) return
|
|
34
|
+
|
|
35
|
+
// Figure out which pairs are active
|
|
36
|
+
const activePairs = []
|
|
37
|
+
if (this.opt.activeOnly) {
|
|
38
|
+
debug({ pairsBeforeCheck: pairs })
|
|
39
|
+
await Promise.all(pairs.map(async pair => {
|
|
40
|
+
const { idle } = await cheapIdleCheck(pair.qname, pair.qrl, this.opt)
|
|
41
|
+
if (!idle) activePairs.push(pair)
|
|
42
|
+
}))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (this.shutdownRequested) return
|
|
46
|
+
|
|
47
|
+
// Finished resolving
|
|
48
|
+
if (this.opt.verbose) {
|
|
49
|
+
console.error(chalk.blue(' done'))
|
|
50
|
+
console.error()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Figure out which queues we want to listen on, choosing between active and
|
|
54
|
+
// all, filtering out failed queues if the user wants that
|
|
55
|
+
this.selectedPairs = (this.opt.activeOnly ? activePairs : pairs)
|
|
56
|
+
.filter(({ qname }) => {
|
|
57
|
+
const suf = this.opt.failSuffix + (this.opt.fifo ? '.fifo' : '')
|
|
58
|
+
const isFailQueue = qname.slice(-suf.length) === suf
|
|
59
|
+
const shouldInclude = this.opt.includeFailed ? true : !isFailQueue
|
|
60
|
+
return shouldInclude
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// Randomize order
|
|
64
|
+
this.selectedPairs.sort(() => 0.5 - Math.random())
|
|
65
|
+
debug('selectedPairs', this.selectedPairs)
|
|
66
|
+
|
|
67
|
+
if (this.opt.verbose) {
|
|
68
|
+
console.error(chalk.blue('Will resolve queues again in ' + this.resolveSeconds + ' seconds'))
|
|
69
|
+
}
|
|
70
|
+
this.resolveTimeout = setTimeout(() => this.resolveQueues(), this.resolveSeconds * 1000)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Return the next queue in the lineup
|
|
74
|
+
nextPair () {
|
|
75
|
+
const pair = this.selectedPairs.shift()
|
|
76
|
+
this.selectedPairs.push(pair)
|
|
77
|
+
return pair
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getPairs () {
|
|
81
|
+
return this.selectedPairs
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
shutdown () {
|
|
85
|
+
clearTimeout(this.resolveTimeout)
|
|
86
|
+
this.shutdownRequested = true
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component to track event loop latency, which can be used as a metric for
|
|
3
|
+
* backpressure.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class SystemMonitor {
|
|
7
|
+
constructor (opt, smoothingFactor = 0.5, reportSeconds = 5) {
|
|
8
|
+
this.opt = opt
|
|
9
|
+
this.smoothingFactor = smoothingFactor
|
|
10
|
+
this.reportSeconds = reportSeconds
|
|
11
|
+
this.measurements = {
|
|
12
|
+
setTimeout: [],
|
|
13
|
+
setImmediate: []
|
|
14
|
+
}
|
|
15
|
+
this.timeouts = {
|
|
16
|
+
setTimeout: undefined,
|
|
17
|
+
setImmediate: undefined,
|
|
18
|
+
reportLatency: undefined
|
|
19
|
+
}
|
|
20
|
+
this.measureLatencySetTimeout()
|
|
21
|
+
this.reportLatency()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
measureLatencySetTimeout () {
|
|
25
|
+
const start = new Date()
|
|
26
|
+
this.timeouts.setTimeout = setTimeout(() => {
|
|
27
|
+
const latency = new Date() - start
|
|
28
|
+
this.measurements.setTimeout.push(latency)
|
|
29
|
+
if (this.measurements.setTimeout.length > 1000) this.measurements.setTimeout.shift()
|
|
30
|
+
this.measureLatencySetTimeout()
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getLatency () {
|
|
35
|
+
const results = {}
|
|
36
|
+
for (const k in this.measurements) {
|
|
37
|
+
const values = this.measurements[k]
|
|
38
|
+
results[k] = values.length ? values.reduce((a, b) => a + b, 0) / values.length : 0
|
|
39
|
+
}
|
|
40
|
+
return results
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
reportLatency () {
|
|
44
|
+
this.timeouts.reportLatency = setTimeout(() => {
|
|
45
|
+
for (const k in this.measurements) {
|
|
46
|
+
const values = this.measurements[k]
|
|
47
|
+
const mean = values.length ? values.reduce((a, b) => a + b, 0) / values.length : 0
|
|
48
|
+
console.log({ [k]: mean })
|
|
49
|
+
}
|
|
50
|
+
this.reportLatency()
|
|
51
|
+
}, this.reportSeconds * 1000)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
shutdown () {
|
|
55
|
+
console.log(this.measurements)
|
|
56
|
+
for (const k in this.timeouts) clearTimeout(this.timeouts[k])
|
|
57
|
+
}
|
|
58
|
+
}
|