pg-boss 8.3.1 → 8.4.1
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 +3 -2
- package/src/attorney.js +14 -0
- package/src/boss.js +1 -1
- package/src/manager.js +5 -5
- package/src/plans.js +8 -4
- package/src/timekeeper.js +32 -14
- package/types.d.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pg-boss",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.4.1",
|
|
4
4
|
"description": "Queueing jobs in Node.js using PostgreSQL like a boss",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"export-schema": "node ./scripts/construct.js",
|
|
33
33
|
"export-migration": "node ./scripts/migrate.js",
|
|
34
34
|
"export-rollback": "node ./scripts/rollback.js",
|
|
35
|
-
"tsc": "tsc --noEmit types.d.ts"
|
|
35
|
+
"tsc": "tsc --noEmit types.d.ts",
|
|
36
|
+
"readme": "node ./test/readme.js"
|
|
36
37
|
},
|
|
37
38
|
"mocha": {
|
|
38
39
|
"timeout": 10000,
|
package/src/attorney.js
CHANGED
|
@@ -159,6 +159,7 @@ function getConfig (value) {
|
|
|
159
159
|
applyDatabaseConfig(config)
|
|
160
160
|
applyMaintenanceConfig(config)
|
|
161
161
|
applyArchiveConfig(config)
|
|
162
|
+
applyArchiveFailedConfig(config)
|
|
162
163
|
applyDeleteConfig(config)
|
|
163
164
|
applyMonitoringConfig(config)
|
|
164
165
|
applyUuidConfig(config)
|
|
@@ -195,6 +196,19 @@ function applyArchiveConfig (config) {
|
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
198
|
|
|
199
|
+
function applyArchiveFailedConfig (config) {
|
|
200
|
+
assert(!('archiveFailedAfterSeconds' in config) || config.archiveFailedAfterSeconds >= 1,
|
|
201
|
+
'configuration assert: archiveFailedAfterSeconds must be at least every second and less than ')
|
|
202
|
+
|
|
203
|
+
config.archiveFailedSeconds = config.archiveFailedAfterSeconds || config.archiveSeconds
|
|
204
|
+
config.archiveFailedInterval = `${config.archiveFailedSeconds} seconds`
|
|
205
|
+
|
|
206
|
+
// Do not emit warning twice
|
|
207
|
+
if (config.archiveFailedSeconds < 60 && config.archiveSeconds >= 60) {
|
|
208
|
+
emitWarning(WARNINGS.CRON_DISABLED)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
198
212
|
function applyCompletionConfig (config, defaults) {
|
|
199
213
|
assert(!('onComplete' in config) || config.onComplete === true || config.onComplete === false,
|
|
200
214
|
'configuration assert: onComplete must be either true or false')
|
package/src/boss.js
CHANGED
|
@@ -33,7 +33,7 @@ class Boss extends EventEmitter {
|
|
|
33
33
|
this.events = events
|
|
34
34
|
|
|
35
35
|
this.expireCommand = plans.locked(config.schema, plans.expire(config.schema))
|
|
36
|
-
this.archiveCommand = plans.locked(config.schema, plans.archive(config.schema, config.archiveInterval))
|
|
36
|
+
this.archiveCommand = plans.locked(config.schema, plans.archive(config.schema, config.archiveInterval, config.archiveFailedInterval))
|
|
37
37
|
this.purgeCommand = plans.locked(config.schema, plans.purge(config.schema, config.deleteAfter))
|
|
38
38
|
this.getMaintenanceTimeCommand = plans.getMaintenanceTime(config.schema)
|
|
39
39
|
this.setMaintenanceTimeCommand = plans.setMaintenanceTime(config.schema)
|
package/src/manager.js
CHANGED
|
@@ -341,7 +341,7 @@ class Manager extends EventEmitter {
|
|
|
341
341
|
}
|
|
342
342
|
|
|
343
343
|
async sendOnce (name, data, options, key) {
|
|
344
|
-
options = options
|
|
344
|
+
options = options ? { ...options } : {}
|
|
345
345
|
|
|
346
346
|
options.singletonKey = key || name
|
|
347
347
|
|
|
@@ -351,7 +351,7 @@ class Manager extends EventEmitter {
|
|
|
351
351
|
}
|
|
352
352
|
|
|
353
353
|
async sendSingleton (name, data, options) {
|
|
354
|
-
options = options
|
|
354
|
+
options = options ? { ...options } : {}
|
|
355
355
|
|
|
356
356
|
options.singletonKey = SINGLETON_QUEUE_KEY
|
|
357
357
|
|
|
@@ -361,7 +361,7 @@ class Manager extends EventEmitter {
|
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
async sendAfter (name, data, options, after) {
|
|
364
|
-
options = options
|
|
364
|
+
options = options ? { ...options } : {}
|
|
365
365
|
options.startAfter = after
|
|
366
366
|
|
|
367
367
|
const result = Attorney.checkSendArgs([name, data, options], this.config)
|
|
@@ -370,7 +370,7 @@ class Manager extends EventEmitter {
|
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
async sendThrottled (name, data, options, seconds, key) {
|
|
373
|
-
options = options
|
|
373
|
+
options = options ? { ...options } : {}
|
|
374
374
|
options.singletonSeconds = seconds
|
|
375
375
|
options.singletonNextSlot = false
|
|
376
376
|
options.singletonKey = key
|
|
@@ -381,7 +381,7 @@ class Manager extends EventEmitter {
|
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
async sendDebounced (name, data, options, seconds, key) {
|
|
384
|
-
options = options
|
|
384
|
+
options = options ? { ...options } : {}
|
|
385
385
|
options.singletonSeconds = seconds
|
|
386
386
|
options.singletonNextSlot = true
|
|
387
387
|
options.singletonKey = key
|
package/src/plans.js
CHANGED
|
@@ -601,7 +601,7 @@ function insertJobs (schema) {
|
|
|
601
601
|
keepUntil,
|
|
602
602
|
on_complete
|
|
603
603
|
)
|
|
604
|
-
SELECT
|
|
604
|
+
SELECT
|
|
605
605
|
COALESCE(id, gen_random_uuid()) as id,
|
|
606
606
|
name,
|
|
607
607
|
data,
|
|
@@ -639,12 +639,16 @@ function purge (schema, interval) {
|
|
|
639
639
|
`
|
|
640
640
|
}
|
|
641
641
|
|
|
642
|
-
function archive (schema,
|
|
642
|
+
function archive (schema, completedInterval, failedInterval = completedInterval) {
|
|
643
643
|
return `
|
|
644
644
|
WITH archived_rows AS (
|
|
645
645
|
DELETE FROM ${schema}.job
|
|
646
|
-
WHERE
|
|
647
|
-
|
|
646
|
+
WHERE (
|
|
647
|
+
state <> '${states.failed}' AND completedOn < (now() - interval '${completedInterval}')
|
|
648
|
+
)
|
|
649
|
+
OR (
|
|
650
|
+
state = '${states.failed}' AND completedOn < (now() - interval '${failedInterval}')
|
|
651
|
+
)
|
|
648
652
|
OR (
|
|
649
653
|
state < '${states.active}' AND keepUntil < now()
|
|
650
654
|
)
|
package/src/timekeeper.js
CHANGED
|
@@ -45,7 +45,7 @@ class Timekeeper extends EventEmitter {
|
|
|
45
45
|
|
|
46
46
|
async start () {
|
|
47
47
|
// setting the archive config too low breaks the cron 60s debounce interval so don't even try
|
|
48
|
-
if (this.config.archiveSeconds < 60) {
|
|
48
|
+
if (this.config.archiveSeconds < 60 || this.config.archiveFailedSeconds < 60) {
|
|
49
49
|
return
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -88,29 +88,47 @@ class Timekeeper extends EventEmitter {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
async monitorCron () {
|
|
91
|
-
|
|
91
|
+
try {
|
|
92
|
+
if (this.config.__test__force_cron_monitoring_error) {
|
|
93
|
+
throw new Error(this.config.__test__force_cron_monitoring_error)
|
|
94
|
+
}
|
|
92
95
|
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
const { secondsAgo } = await this.getCronTime()
|
|
97
|
+
|
|
98
|
+
if (secondsAgo > 60) {
|
|
99
|
+
await this.checkSchedulesAsync()
|
|
100
|
+
}
|
|
101
|
+
} catch (err) {
|
|
102
|
+
this.emit(this.events.error, err)
|
|
95
103
|
}
|
|
96
104
|
}
|
|
97
105
|
|
|
98
106
|
async cacheClockSkew () {
|
|
99
|
-
|
|
107
|
+
let skew = 0
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
if (this.config.__test__force_clock_monitoring_error) {
|
|
111
|
+
throw new Error(this.config.__test__force_clock_monitoring_error)
|
|
112
|
+
}
|
|
100
113
|
|
|
101
|
-
|
|
114
|
+
const { rows } = await this.db.executeSql(this.getTimeCommand)
|
|
102
115
|
|
|
103
|
-
|
|
116
|
+
const local = Date.now()
|
|
104
117
|
|
|
105
|
-
|
|
118
|
+
const dbTime = parseFloat(rows[0].time)
|
|
106
119
|
|
|
107
|
-
|
|
120
|
+
skew = dbTime - local
|
|
108
121
|
|
|
109
|
-
|
|
110
|
-
Attorney.warnClockSkew(`Instance clock is ${skewSeconds}s ${skew > 0 ? 'slower' : 'faster'} than database.`)
|
|
111
|
-
}
|
|
122
|
+
const skewSeconds = Math.abs(skew) / 1000
|
|
112
123
|
|
|
113
|
-
|
|
124
|
+
if (skewSeconds >= 60 || this.config.__test__force_clock_skew_warning) {
|
|
125
|
+
Attorney.warnClockSkew(`Instance clock is ${skewSeconds}s ${skew > 0 ? 'slower' : 'faster'} than database.`)
|
|
126
|
+
}
|
|
127
|
+
} catch (err) {
|
|
128
|
+
this.emit(this.events.error, err)
|
|
129
|
+
} finally {
|
|
130
|
+
this.clockSkew = skew
|
|
131
|
+
}
|
|
114
132
|
}
|
|
115
133
|
|
|
116
134
|
async checkSchedulesAsync () {
|
|
@@ -128,7 +146,7 @@ class Timekeeper extends EventEmitter {
|
|
|
128
146
|
|
|
129
147
|
try {
|
|
130
148
|
if (this.config.__test__throw_clock_monitoring) {
|
|
131
|
-
throw new Error(
|
|
149
|
+
throw new Error(this.config.__test__throw_clock_monitoring)
|
|
132
150
|
}
|
|
133
151
|
|
|
134
152
|
const items = await this.getSchedules()
|