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.
@@ -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
+ }