pg-boss 9.0.2 → 10.0.0-beta1
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/README.md +9 -22
- package/package.json +3 -8
- package/src/attorney.js +74 -85
- package/src/boss.js +97 -132
- package/src/contractor.js +14 -0
- package/src/db.js +40 -0
- package/src/index.js +65 -55
- package/src/manager.js +211 -115
- package/src/migrationStore.js +127 -71
- package/src/plans.js +336 -291
- package/src/timekeeper.js +4 -6
- package/src/tools.js +28 -0
- package/src/worker.js +3 -3
- package/types.d.ts +16 -34
- package/version.json +1 -1
- package/coverage/lcov-report/attorney.js.html +0 -1342
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/boss.js.html +0 -850
- package/coverage/lcov-report/contractor.js.html +0 -322
- package/coverage/lcov-report/db.js.html +0 -208
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -251
- package/coverage/lcov-report/index.js.html +0 -634
- package/coverage/lcov-report/manager.js.html +0 -1930
- package/coverage/lcov-report/migrationStore.js.html +0 -604
- package/coverage/lcov-report/plans.js.html +0 -2224
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov-report/timekeeper.js.html +0 -814
- package/coverage/lcov-report/worker.js.html +0 -382
- package/coverage/lcov.info +0 -2058
package/src/boss.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
const EventEmitter = require('events')
|
|
2
2
|
const plans = require('./plans')
|
|
3
|
-
const {
|
|
4
|
-
const { COMPLETION_JOB_PREFIX } = plans
|
|
5
|
-
|
|
6
|
-
const queues = {
|
|
7
|
-
MAINTENANCE: '__pgboss__maintenance',
|
|
8
|
-
MONITOR_STATES: '__pgboss__monitor-states'
|
|
9
|
-
}
|
|
3
|
+
const { delay } = require('./tools')
|
|
10
4
|
|
|
11
5
|
const events = {
|
|
12
6
|
error: 'error',
|
|
@@ -23,165 +17,135 @@ class Boss extends EventEmitter {
|
|
|
23
17
|
this.manager = config.manager
|
|
24
18
|
|
|
25
19
|
this.maintenanceIntervalSeconds = config.maintenanceIntervalSeconds
|
|
26
|
-
|
|
27
|
-
this.monitorStates = config.monitorStateIntervalSeconds !== null
|
|
28
|
-
|
|
29
|
-
if (this.monitorStates) {
|
|
30
|
-
this.monitorIntervalSeconds = config.monitorStateIntervalSeconds
|
|
31
|
-
}
|
|
20
|
+
this.monitorStateIntervalSeconds = config.monitorStateIntervalSeconds
|
|
32
21
|
|
|
33
22
|
this.events = events
|
|
34
23
|
|
|
35
|
-
this.
|
|
24
|
+
this.failJobsByTimeoutCommand = plans.locked(config.schema, plans.failJobsByTimeout(config.schema))
|
|
36
25
|
this.archiveCommand = plans.locked(config.schema, plans.archive(config.schema, config.archiveInterval, config.archiveFailedInterval))
|
|
37
|
-
this.
|
|
26
|
+
this.dropCommand = plans.locked(config.schema, plans.drop(config.schema, config.deleteAfter))
|
|
38
27
|
this.getMaintenanceTimeCommand = plans.getMaintenanceTime(config.schema)
|
|
39
28
|
this.setMaintenanceTimeCommand = plans.setMaintenanceTime(config.schema)
|
|
29
|
+
this.getMonitorTimeCommand = plans.getMonitorTime(config.schema)
|
|
30
|
+
this.setMonitorTimeCommand = plans.setMonitorTime(config.schema)
|
|
40
31
|
this.countStatesCommand = plans.countStates(config.schema)
|
|
41
32
|
|
|
42
33
|
this.functions = [
|
|
43
34
|
this.expire,
|
|
44
35
|
this.archive,
|
|
45
|
-
this.
|
|
36
|
+
this.drop,
|
|
46
37
|
this.countStates,
|
|
47
|
-
this.
|
|
38
|
+
this.maintain
|
|
48
39
|
]
|
|
49
40
|
}
|
|
50
41
|
|
|
51
42
|
async supervise () {
|
|
52
|
-
this.
|
|
43
|
+
this.maintenanceInterval = setInterval(() => this.onSupervise(), this.maintenanceIntervalSeconds * 1000)
|
|
44
|
+
}
|
|
53
45
|
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
async monitor () {
|
|
47
|
+
this.monitorInterval = setInterval(() => this.onMonitor(), this.monitorStateIntervalSeconds * 1000)
|
|
48
|
+
}
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
async onMonitor () {
|
|
51
|
+
let locker
|
|
58
52
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
await this.manager.work(queues.MAINTENANCE, maintenanceWorkOptions, (job) => this.onMaintenance(job))
|
|
53
|
+
try {
|
|
54
|
+
if (this.monitoring) {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
64
57
|
|
|
65
|
-
|
|
66
|
-
await this.manager.deleteQueue(COMPLETION_JOB_PREFIX + queues.MONITOR_STATES)
|
|
67
|
-
await this.manager.deleteQueue(queues.MONITOR_STATES)
|
|
58
|
+
this.monitoring = true
|
|
68
59
|
|
|
69
|
-
|
|
60
|
+
if (this.config.__test__delay_monitor) {
|
|
61
|
+
await delay(this.config.__test__delay_monitor)
|
|
62
|
+
}
|
|
70
63
|
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
if (this.config.__test__throw_monitor) {
|
|
65
|
+
throw new Error(this.config.__test__throw_monitor)
|
|
73
66
|
}
|
|
74
67
|
|
|
75
|
-
await this.
|
|
76
|
-
}
|
|
77
|
-
}
|
|
68
|
+
locker = await this.db.lock({ key: 'monitor' })
|
|
78
69
|
|
|
79
|
-
|
|
80
|
-
this.metaMonitorInterval = setInterval(async () => {
|
|
81
|
-
try {
|
|
82
|
-
if (this.config.__test__throw_meta_monitor) {
|
|
83
|
-
throw new Error(this.config.__test__throw_meta_monitor)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const { secondsAgo } = await this.getMaintenanceTime()
|
|
87
|
-
|
|
88
|
-
if (secondsAgo > this.maintenanceIntervalSeconds * 2) {
|
|
89
|
-
await this.manager.deleteQueue(queues.MAINTENANCE, { before: states.completed })
|
|
90
|
-
await this.maintenanceAsync()
|
|
91
|
-
}
|
|
92
|
-
} catch (err) {
|
|
93
|
-
this.emit(events.error, err)
|
|
94
|
-
}
|
|
95
|
-
}, this.maintenanceIntervalSeconds * 2 * 1000)
|
|
96
|
-
}
|
|
70
|
+
const { secondsAgo } = await this.getMonitorTime()
|
|
97
71
|
|
|
98
|
-
|
|
99
|
-
|
|
72
|
+
if (secondsAgo > this.monitorStateIntervalSeconds && !this.stopped) {
|
|
73
|
+
const states = await this.countStates()
|
|
74
|
+
this.setMonitorTime()
|
|
75
|
+
this.emit(events.monitorStates, states)
|
|
76
|
+
}
|
|
77
|
+
} catch (err) {
|
|
78
|
+
this.emit(events.error, err)
|
|
79
|
+
} finally {
|
|
80
|
+
if (locker?.locked) {
|
|
81
|
+
await locker.unlock()
|
|
82
|
+
}
|
|
100
83
|
|
|
101
|
-
|
|
102
|
-
startAfter,
|
|
103
|
-
retentionSeconds: this.maintenanceIntervalSeconds * 4,
|
|
104
|
-
singletonKey: queues.MAINTENANCE,
|
|
105
|
-
onComplete: false
|
|
84
|
+
this.monitoring = false
|
|
106
85
|
}
|
|
107
|
-
|
|
108
|
-
await this.manager.send(queues.MAINTENANCE, null, options)
|
|
109
86
|
}
|
|
110
87
|
|
|
111
|
-
async
|
|
112
|
-
|
|
88
|
+
async onSupervise () {
|
|
89
|
+
let locker
|
|
113
90
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
onComplete: false
|
|
119
|
-
}
|
|
91
|
+
try {
|
|
92
|
+
if (this.maintaining) {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
120
95
|
|
|
121
|
-
|
|
122
|
-
|
|
96
|
+
this.maintaining = true
|
|
97
|
+
|
|
98
|
+
if (this.config.__test__delay_maintenance && !this.stopped) {
|
|
99
|
+
this.__testDelayPromise = delay(this.config.__test__delay_maintenance)
|
|
100
|
+
await this.__testDelayPromise
|
|
101
|
+
}
|
|
123
102
|
|
|
124
|
-
async onMaintenance (job) {
|
|
125
|
-
try {
|
|
126
103
|
if (this.config.__test__throw_maint) {
|
|
127
104
|
throw new Error(this.config.__test__throw_maint)
|
|
128
105
|
}
|
|
129
106
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
await this.archive()
|
|
134
|
-
await this.purge()
|
|
135
|
-
|
|
136
|
-
const ended = Date.now()
|
|
107
|
+
if (this.stopped) {
|
|
108
|
+
return
|
|
109
|
+
}
|
|
137
110
|
|
|
138
|
-
await this.
|
|
111
|
+
locker = await this.db.lock({ key: 'maintenance' })
|
|
139
112
|
|
|
140
|
-
|
|
113
|
+
const { secondsAgo } = await this.getMaintenanceTime()
|
|
141
114
|
|
|
142
|
-
if (
|
|
143
|
-
await this.
|
|
144
|
-
|
|
115
|
+
if (secondsAgo > this.maintenanceIntervalSeconds) {
|
|
116
|
+
const result = await this.maintain()
|
|
117
|
+
this.emit(events.maintenance, result)
|
|
145
118
|
}
|
|
146
119
|
} catch (err) {
|
|
147
120
|
this.emit(events.error, err)
|
|
121
|
+
} finally {
|
|
122
|
+
if (locker?.locked) {
|
|
123
|
+
await locker.unlock()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.maintaining = false
|
|
148
127
|
}
|
|
149
128
|
}
|
|
150
129
|
|
|
151
|
-
async
|
|
152
|
-
|
|
153
|
-
if (this.config.__test__throw_monitor) {
|
|
154
|
-
throw new Error(this.config.__test__throw_monitor)
|
|
155
|
-
}
|
|
130
|
+
async maintain () {
|
|
131
|
+
const started = Date.now()
|
|
156
132
|
|
|
157
|
-
|
|
133
|
+
!this.stopped && await this.expire()
|
|
134
|
+
!this.stopped && await this.archive()
|
|
135
|
+
!this.stopped && await this.drop()
|
|
158
136
|
|
|
159
|
-
|
|
137
|
+
const ended = Date.now()
|
|
160
138
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
} catch (err) {
|
|
166
|
-
this.emit(events.error, err)
|
|
167
|
-
}
|
|
139
|
+
await this.setMaintenanceTime()
|
|
140
|
+
|
|
141
|
+
return { ms: ended - started }
|
|
168
142
|
}
|
|
169
143
|
|
|
170
144
|
async stop () {
|
|
171
|
-
if (this.config.__test__throw_stop) {
|
|
172
|
-
throw new Error(this.config.__test__throw_stop)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
145
|
if (!this.stopped) {
|
|
176
|
-
if (this.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
await this.manager.offWork(queues.MAINTENANCE)
|
|
181
|
-
|
|
182
|
-
if (this.monitorStates) {
|
|
183
|
-
await this.manager.offWork(queues.MONITOR_STATES)
|
|
184
|
-
}
|
|
146
|
+
if (this.__testDelayPromise) this.__testDelayPromise.abort()
|
|
147
|
+
if (this.maintenanceInterval) clearInterval(this.maintenanceInterval)
|
|
148
|
+
if (this.monitorInterval) clearInterval(this.monitorInterval)
|
|
185
149
|
|
|
186
150
|
this.stopped = true
|
|
187
151
|
}
|
|
@@ -193,7 +157,7 @@ class Boss extends EventEmitter {
|
|
|
193
157
|
Object.keys(stateCountDefault)
|
|
194
158
|
.forEach(key => { stateCountDefault[key] = 0 })
|
|
195
159
|
|
|
196
|
-
const counts = await this.executeSql(this.countStatesCommand)
|
|
160
|
+
const counts = await this.db.executeSql(this.countStatesCommand)
|
|
197
161
|
|
|
198
162
|
const states = counts.rows.reduce((acc, item) => {
|
|
199
163
|
if (item.name) {
|
|
@@ -213,43 +177,44 @@ class Boss extends EventEmitter {
|
|
|
213
177
|
}
|
|
214
178
|
|
|
215
179
|
async expire () {
|
|
216
|
-
await this.executeSql(this.
|
|
180
|
+
await this.db.executeSql(this.failJobsByTimeoutCommand)
|
|
217
181
|
}
|
|
218
182
|
|
|
219
183
|
async archive () {
|
|
220
|
-
await this.executeSql(this.archiveCommand)
|
|
184
|
+
await this.db.executeSql(this.archiveCommand)
|
|
221
185
|
}
|
|
222
186
|
|
|
223
|
-
async
|
|
224
|
-
await this.executeSql(this.
|
|
187
|
+
async drop () {
|
|
188
|
+
await this.db.executeSql(this.dropCommand)
|
|
225
189
|
}
|
|
226
190
|
|
|
227
191
|
async setMaintenanceTime () {
|
|
228
|
-
await this.executeSql(this.setMaintenanceTimeCommand)
|
|
192
|
+
await this.db.executeSql(this.setMaintenanceTimeCommand)
|
|
229
193
|
}
|
|
230
194
|
|
|
231
195
|
async getMaintenanceTime () {
|
|
232
|
-
|
|
233
|
-
const { rows } = await this.db.executeSql(this.getMaintenanceTimeCommand)
|
|
196
|
+
const { rows } = await this.db.executeSql(this.getMaintenanceTimeCommand)
|
|
234
197
|
|
|
235
|
-
|
|
198
|
+
let { maintained_on: maintainedOn, seconds_ago: secondsAgo } = rows[0]
|
|
236
199
|
|
|
237
|
-
|
|
200
|
+
secondsAgo = secondsAgo !== null ? parseFloat(secondsAgo) : 999_999_999
|
|
238
201
|
|
|
239
|
-
|
|
240
|
-
}
|
|
202
|
+
return { maintainedOn, secondsAgo }
|
|
241
203
|
}
|
|
242
204
|
|
|
243
|
-
|
|
244
|
-
|
|
205
|
+
async setMonitorTime () {
|
|
206
|
+
await this.db.executeSql(this.setMonitorTimeCommand)
|
|
245
207
|
}
|
|
246
208
|
|
|
247
|
-
async
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
209
|
+
async getMonitorTime () {
|
|
210
|
+
const { rows } = await this.db.executeSql(this.getMonitorTimeCommand)
|
|
211
|
+
|
|
212
|
+
let { monitored_on: monitoredOn, seconds_ago: secondsAgo } = rows[0]
|
|
213
|
+
|
|
214
|
+
secondsAgo = secondsAgo !== null ? parseFloat(secondsAgo) : 999_999_999
|
|
215
|
+
|
|
216
|
+
return { monitoredOn, secondsAgo }
|
|
251
217
|
}
|
|
252
218
|
}
|
|
253
219
|
|
|
254
220
|
module.exports = Boss
|
|
255
|
-
module.exports.QUEUES = queues
|
package/src/contractor.js
CHANGED
|
@@ -47,6 +47,20 @@ class Contractor {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
async check () {
|
|
51
|
+
const installed = await this.isInstalled()
|
|
52
|
+
|
|
53
|
+
if (!installed) {
|
|
54
|
+
throw new Error('pg-boss is not installed')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const version = await this.version()
|
|
58
|
+
|
|
59
|
+
if (schemaVersion !== version) {
|
|
60
|
+
throw new Error('pg-boss database requires migrations')
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
50
64
|
async create () {
|
|
51
65
|
try {
|
|
52
66
|
const commands = plans.create(this.config.schema, schemaVersion)
|
package/src/db.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const EventEmitter = require('events')
|
|
2
2
|
const pg = require('pg')
|
|
3
|
+
const { advisoryLock } = require('./plans')
|
|
3
4
|
|
|
4
5
|
class Db extends EventEmitter {
|
|
5
6
|
constructor (config) {
|
|
@@ -25,10 +26,49 @@ class Db extends EventEmitter {
|
|
|
25
26
|
|
|
26
27
|
async executeSql (text, values) {
|
|
27
28
|
if (this.opened) {
|
|
29
|
+
// if (this.config.debug === true) {
|
|
30
|
+
// console.log(`${new Date().toISOString()}: DEBUG SQL`)
|
|
31
|
+
// console.log(text)
|
|
32
|
+
|
|
33
|
+
// if (values) {
|
|
34
|
+
// console.log(`${new Date().toISOString()}: DEBUG VALUES`)
|
|
35
|
+
// console.log(values)
|
|
36
|
+
// }
|
|
37
|
+
// }
|
|
38
|
+
|
|
28
39
|
return await this.pool.query(text, values)
|
|
29
40
|
}
|
|
30
41
|
}
|
|
31
42
|
|
|
43
|
+
async lock ({ timeout = 30, key } = {}) {
|
|
44
|
+
// const lockedClient = new pg.Client(this.config)
|
|
45
|
+
// await lockedClient.connect()
|
|
46
|
+
const lockedClient = await this.pool.connect()
|
|
47
|
+
|
|
48
|
+
const query = `
|
|
49
|
+
BEGIN;
|
|
50
|
+
SET LOCAL lock_timeout = '${timeout}s';
|
|
51
|
+
SET LOCAL idle_in_transaction_session_timeout = '3600s';
|
|
52
|
+
${advisoryLock(this.config.schema, key)};
|
|
53
|
+
`
|
|
54
|
+
|
|
55
|
+
await lockedClient.query(query)
|
|
56
|
+
|
|
57
|
+
const locker = {
|
|
58
|
+
locked: true,
|
|
59
|
+
unlock: async function () {
|
|
60
|
+
try {
|
|
61
|
+
await lockedClient.query('COMMIT')
|
|
62
|
+
await lockedClient.end()
|
|
63
|
+
} finally {
|
|
64
|
+
this.locked = false
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return locker
|
|
70
|
+
}
|
|
71
|
+
|
|
32
72
|
static quotePostgresStr (str) {
|
|
33
73
|
const delimeter = '$sanitize$'
|
|
34
74
|
if (str.includes(delimeter)) {
|
package/src/index.js
CHANGED
|
@@ -6,7 +6,7 @@ const Manager = require('./manager')
|
|
|
6
6
|
const Timekeeper = require('./timekeeper')
|
|
7
7
|
const Boss = require('./boss')
|
|
8
8
|
const Db = require('./db')
|
|
9
|
-
const delay = require('
|
|
9
|
+
const { delay } = require('./tools')
|
|
10
10
|
|
|
11
11
|
const events = {
|
|
12
12
|
error: 'error',
|
|
@@ -72,16 +72,7 @@ class PgBoss extends EventEmitter {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
function promoteFunction (obj, func) {
|
|
75
|
-
this[func.name] = (...args) =>
|
|
76
|
-
const shouldRun = !this.started || !((func.name === 'work' || func.name === 'onComplete') && (this.stopped || this.stoppingOn))
|
|
77
|
-
|
|
78
|
-
if (shouldRun) {
|
|
79
|
-
return func.apply(obj, args)
|
|
80
|
-
} else {
|
|
81
|
-
const state = this.stoppingOn ? 'stopping' : this.stopped ? 'stopped' : !this.started ? 'not started' : 'started'
|
|
82
|
-
return Promise.reject(new Error(`pg-boss is ${state}.`))
|
|
83
|
-
}
|
|
84
|
-
}
|
|
75
|
+
this[func.name] = (...args) => func.apply(obj, args)
|
|
85
76
|
}
|
|
86
77
|
|
|
87
78
|
function promoteEvent (emitter, event) {
|
|
@@ -90,42 +81,49 @@ class PgBoss extends EventEmitter {
|
|
|
90
81
|
}
|
|
91
82
|
|
|
92
83
|
async start () {
|
|
93
|
-
if (
|
|
94
|
-
return
|
|
84
|
+
if (this.starting || this.started) {
|
|
85
|
+
return
|
|
95
86
|
}
|
|
96
87
|
|
|
88
|
+
this.starting = true
|
|
89
|
+
|
|
97
90
|
if (this.db.isOurs && !this.db.opened) {
|
|
98
91
|
await this.db.open()
|
|
99
92
|
}
|
|
100
93
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
if (this.config.migrate) {
|
|
95
|
+
await this.contractor.start()
|
|
96
|
+
} else {
|
|
97
|
+
await this.contractor.check()
|
|
98
|
+
}
|
|
105
99
|
|
|
106
100
|
this.manager.start()
|
|
107
101
|
|
|
108
|
-
if (
|
|
102
|
+
if (this.config.supervise) {
|
|
109
103
|
await this.boss.supervise()
|
|
110
104
|
}
|
|
111
105
|
|
|
112
|
-
if (
|
|
106
|
+
if (this.config.monitorStateIntervalSeconds) {
|
|
107
|
+
await this.boss.monitor()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (this.config.schedule) {
|
|
113
111
|
await this.timekeeper.start()
|
|
114
112
|
}
|
|
115
113
|
|
|
114
|
+
this.starting = false
|
|
115
|
+
this.started = true
|
|
116
|
+
this.stopped = false
|
|
117
|
+
|
|
116
118
|
return this
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
async stop (options = {}) {
|
|
120
|
-
if (this.stoppingOn) {
|
|
122
|
+
if (this.stoppingOn || this.stopped) {
|
|
121
123
|
return
|
|
122
124
|
}
|
|
123
125
|
|
|
124
|
-
|
|
125
|
-
this.emit(events.stopped)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let { destroy = false, graceful = true, timeout = 30000 } = options
|
|
126
|
+
let { destroy = false, graceful = true, timeout = 30000, wait = true } = options
|
|
129
127
|
|
|
130
128
|
timeout = Math.max(timeout, 1000)
|
|
131
129
|
|
|
@@ -133,47 +131,59 @@ class PgBoss extends EventEmitter {
|
|
|
133
131
|
|
|
134
132
|
await this.manager.stop()
|
|
135
133
|
await this.timekeeper.stop()
|
|
134
|
+
await this.boss.stop()
|
|
136
135
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
await new Promise((resolve, reject) => {
|
|
137
|
+
const shutdown = async () => {
|
|
138
|
+
try {
|
|
139
|
+
if (this.config.__test__throw_shutdown) {
|
|
140
|
+
throw new Error(this.config.__test__throw_shutdown)
|
|
141
|
+
}
|
|
140
142
|
|
|
141
|
-
|
|
142
|
-
await this.db.close()
|
|
143
|
-
}
|
|
143
|
+
await this.manager.failWip()
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
if (this.db.isOurs && this.db.opened && destroy) {
|
|
146
|
+
await this.db.close()
|
|
147
|
+
}
|
|
147
148
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return
|
|
152
|
-
}
|
|
149
|
+
this.stopped = true
|
|
150
|
+
this.stoppingOn = null
|
|
151
|
+
this.started = false
|
|
153
152
|
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
this.emit(events.stopped)
|
|
154
|
+
resolve()
|
|
155
|
+
} catch (err) {
|
|
156
|
+
this.emit(events.error, err)
|
|
157
|
+
reject(err)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
156
160
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (closing) {
|
|
161
|
-
break
|
|
162
|
-
}
|
|
161
|
+
if (!graceful) {
|
|
162
|
+
return shutdown()
|
|
163
|
+
}
|
|
163
164
|
|
|
164
|
-
|
|
165
|
+
if (!wait) {
|
|
166
|
+
resolve()
|
|
167
|
+
}
|
|
165
168
|
|
|
166
|
-
|
|
169
|
+
setImmediate(async () => {
|
|
170
|
+
try {
|
|
171
|
+
if (this.config.__test__throw_stop_monitor) {
|
|
172
|
+
throw new Error(this.config.__test__throw_stop_monitor)
|
|
167
173
|
}
|
|
168
174
|
|
|
169
|
-
|
|
170
|
-
}
|
|
175
|
+
const isWip = () => this.manager.getWipData({ includeInternal: false }).length > 0
|
|
171
176
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
while ((Date.now() - this.stoppingOn) < timeout && isWip()) {
|
|
178
|
+
await delay(500)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
await shutdown()
|
|
182
|
+
} catch (err) {
|
|
183
|
+
reject(err)
|
|
184
|
+
this.emit(events.error, err)
|
|
185
|
+
}
|
|
186
|
+
})
|
|
177
187
|
})
|
|
178
188
|
}
|
|
179
189
|
}
|