pg-boss 10.0.0-beta7 → 10.0.0-beta9
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 +1 -1
- package/src/boss.js +4 -3
- package/src/index.js +3 -1
- package/src/manager.js +3 -3
- package/src/plans.js +46 -46
- package/types.d.ts +19 -0
package/package.json
CHANGED
package/src/boss.js
CHANGED
|
@@ -135,10 +135,11 @@ class Boss extends EventEmitter {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
async countStates () {
|
|
138
|
-
const stateCountDefault = { ...plans.
|
|
138
|
+
const stateCountDefault = { ...plans.JOB_STATES }
|
|
139
139
|
|
|
140
|
-
Object.keys(stateCountDefault)
|
|
141
|
-
|
|
140
|
+
for (const key of Object.keys(stateCountDefault)) {
|
|
141
|
+
stateCountDefault[key] = 0
|
|
142
|
+
}
|
|
142
143
|
|
|
143
144
|
const counts = await this.db.executeSql(this.countStatesCommand)
|
|
144
145
|
|
package/src/index.js
CHANGED
|
@@ -36,6 +36,9 @@ class PgBoss extends EventEmitter {
|
|
|
36
36
|
return Contractor.rollbackPlans(schema, version)
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
static states = plans.JOB_STATES
|
|
40
|
+
static policies = plans.QUEUE_POLICIES
|
|
41
|
+
|
|
39
42
|
constructor (value) {
|
|
40
43
|
super()
|
|
41
44
|
|
|
@@ -212,4 +215,3 @@ class PgBoss extends EventEmitter {
|
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
module.exports = PgBoss
|
|
215
|
-
module.exports.states = plans.states
|
package/src/manager.js
CHANGED
|
@@ -10,7 +10,7 @@ const Worker = require('./worker')
|
|
|
10
10
|
const plans = require('./plans')
|
|
11
11
|
|
|
12
12
|
const { QUEUES: TIMEKEEPER_QUEUES } = require('./timekeeper')
|
|
13
|
-
const {
|
|
13
|
+
const { QUEUE_POLICIES } = plans
|
|
14
14
|
|
|
15
15
|
const INTERNAL_QUEUES = Object.values(TIMEKEEPER_QUEUES).reduce((acc, i) => ({ ...acc, [i]: i }), {})
|
|
16
16
|
|
|
@@ -545,9 +545,9 @@ class Manager extends EventEmitter {
|
|
|
545
545
|
|
|
546
546
|
Attorney.assertQueueName(name)
|
|
547
547
|
|
|
548
|
-
const { policy =
|
|
548
|
+
const { policy = QUEUE_POLICIES.standard } = options
|
|
549
549
|
|
|
550
|
-
assert(policy in
|
|
550
|
+
assert(policy in QUEUE_POLICIES, `${policy} is not a valid queue policy`)
|
|
551
551
|
|
|
552
552
|
const {
|
|
553
553
|
retryLimit,
|
package/src/plans.js
CHANGED
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
const
|
|
1
|
+
const DEFAULT_SCHEMA = 'pgboss'
|
|
2
|
+
const MIGRATE_RACE_MESSAGE = 'division by zero'
|
|
3
|
+
const CREATE_RACE_MESSAGE = 'already exists'
|
|
2
4
|
|
|
3
|
-
const
|
|
5
|
+
const JOB_STATES = Object.freeze({
|
|
4
6
|
created: 'created',
|
|
5
7
|
retry: 'retry',
|
|
6
8
|
active: 'active',
|
|
7
9
|
completed: 'completed',
|
|
8
10
|
cancelled: 'cancelled',
|
|
9
11
|
failed: 'failed'
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const DEFAULT_SCHEMA = 'pgboss'
|
|
13
|
-
const MIGRATE_RACE_MESSAGE = 'division by zero'
|
|
14
|
-
const CREATE_RACE_MESSAGE = 'already exists'
|
|
12
|
+
})
|
|
15
13
|
|
|
16
|
-
const
|
|
14
|
+
const QUEUE_POLICIES = Object.freeze({
|
|
17
15
|
standard: 'standard',
|
|
18
16
|
short: 'short',
|
|
19
17
|
singleton: 'singleton',
|
|
20
18
|
stately: 'stately'
|
|
21
|
-
}
|
|
19
|
+
})
|
|
22
20
|
|
|
23
21
|
module.exports = {
|
|
24
22
|
create,
|
|
@@ -60,13 +58,15 @@ module.exports = {
|
|
|
60
58
|
assertMigration,
|
|
61
59
|
getArchivedJobById,
|
|
62
60
|
getJobById,
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
QUEUE_POLICIES,
|
|
62
|
+
JOB_STATES,
|
|
65
63
|
MIGRATE_RACE_MESSAGE,
|
|
66
64
|
CREATE_RACE_MESSAGE,
|
|
67
65
|
DEFAULT_SCHEMA
|
|
68
66
|
}
|
|
69
67
|
|
|
68
|
+
const assert = require('assert')
|
|
69
|
+
|
|
70
70
|
function create (schema, version) {
|
|
71
71
|
const commands = [
|
|
72
72
|
createSchema(schema),
|
|
@@ -122,12 +122,12 @@ function createEnumJobState (schema) {
|
|
|
122
122
|
// base type is numeric and first values are less than last values
|
|
123
123
|
return `
|
|
124
124
|
CREATE TYPE ${schema}.job_state AS ENUM (
|
|
125
|
-
'${
|
|
126
|
-
'${
|
|
127
|
-
'${
|
|
128
|
-
'${
|
|
129
|
-
'${
|
|
130
|
-
'${
|
|
125
|
+
'${JOB_STATES.created}',
|
|
126
|
+
'${JOB_STATES.retry}',
|
|
127
|
+
'${JOB_STATES.active}',
|
|
128
|
+
'${JOB_STATES.completed}',
|
|
129
|
+
'${JOB_STATES.cancelled}',
|
|
130
|
+
'${JOB_STATES.failed}'
|
|
131
131
|
)
|
|
132
132
|
`
|
|
133
133
|
}
|
|
@@ -139,7 +139,7 @@ function createTableJob (schema) {
|
|
|
139
139
|
name text not null,
|
|
140
140
|
priority integer not null default(0),
|
|
141
141
|
data jsonb,
|
|
142
|
-
state ${schema}.job_state not null default('${
|
|
142
|
+
state ${schema}.job_state not null default('${JOB_STATES.created}'),
|
|
143
143
|
retry_limit integer not null default(0),
|
|
144
144
|
retry_count integer not null default(0),
|
|
145
145
|
retry_delay integer not null default(0),
|
|
@@ -186,7 +186,7 @@ function getPartitionFunction (schema) {
|
|
|
186
186
|
return `
|
|
187
187
|
CREATE FUNCTION ${schema}.get_partition(queue_name text, out name text) AS
|
|
188
188
|
$$
|
|
189
|
-
SELECT '
|
|
189
|
+
SELECT 'job_' || encode(sha224(queue_name::bytea), 'hex');
|
|
190
190
|
$$
|
|
191
191
|
LANGUAGE SQL
|
|
192
192
|
IMMUTABLE
|
|
@@ -201,9 +201,9 @@ function createPartitionFunction (schema) {
|
|
|
201
201
|
DECLARE
|
|
202
202
|
table_name varchar := ${schema}.get_partition(queue_name);
|
|
203
203
|
BEGIN
|
|
204
|
-
EXECUTE format('CREATE TABLE
|
|
205
|
-
EXECUTE format('ALTER TABLE
|
|
206
|
-
EXECUTE format('ALTER TABLE ${schema}.job ATTACH PARTITION
|
|
204
|
+
EXECUTE format('CREATE TABLE ${schema}.%I (LIKE ${schema}.job INCLUDING DEFAULTS INCLUDING CONSTRAINTS)', table_name);
|
|
205
|
+
EXECUTE format('ALTER TABLE ${schema}.%I ADD CHECK (name=%L)', table_name, queue_name);
|
|
206
|
+
EXECUTE format('ALTER TABLE ${schema}.job ATTACH PARTITION ${schema}.%I FOR VALUES IN (%L)', table_name, queue_name);
|
|
207
207
|
END;
|
|
208
208
|
$$
|
|
209
209
|
LANGUAGE plpgsql;
|
|
@@ -232,27 +232,27 @@ function createPrimaryKeyArchive (schema) {
|
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
function createIndexJobPolicyShort (schema) {
|
|
235
|
-
return `CREATE UNIQUE INDEX job_policy_short ON ${schema}.job (name) WHERE state = '${
|
|
235
|
+
return `CREATE UNIQUE INDEX job_policy_short ON ${schema}.job (name) WHERE state = '${JOB_STATES.created}' AND policy = '${QUEUE_POLICIES.short}'`
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
function createIndexJobPolicySingleton (schema) {
|
|
239
|
-
return `CREATE UNIQUE INDEX job_policy_singleton ON ${schema}.job (name) WHERE state = '${
|
|
239
|
+
return `CREATE UNIQUE INDEX job_policy_singleton ON ${schema}.job (name) WHERE state = '${JOB_STATES.active}' AND policy = '${QUEUE_POLICIES.singleton}'`
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
function createIndexJobPolicyStately (schema) {
|
|
243
|
-
return `CREATE UNIQUE INDEX job_policy_stately ON ${schema}.job (name, state) WHERE state <= '${
|
|
243
|
+
return `CREATE UNIQUE INDEX job_policy_stately ON ${schema}.job (name, state) WHERE state <= '${JOB_STATES.active}' AND policy = '${QUEUE_POLICIES.stately}'`
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
function createIndexJobThrottleOn (schema) {
|
|
247
|
-
return `CREATE UNIQUE INDEX job_throttle_on ON ${schema}.job (name, singleton_on, COALESCE(singleton_key, '')) WHERE state <= '${
|
|
247
|
+
return `CREATE UNIQUE INDEX job_throttle_on ON ${schema}.job (name, singleton_on, COALESCE(singleton_key, '')) WHERE state <= '${JOB_STATES.completed}' AND singleton_on IS NOT NULL`
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
function createIndexJobThrottleKey (schema) {
|
|
251
|
-
return `CREATE UNIQUE INDEX job_throttle_key ON ${schema}.job (name, singleton_key) WHERE state <= '${
|
|
251
|
+
return `CREATE UNIQUE INDEX job_throttle_key ON ${schema}.job (name, singleton_key) WHERE state <= '${JOB_STATES.completed}' AND singleton_on IS NULL`
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
function createIndexJobFetch (schema) {
|
|
255
|
-
return `CREATE INDEX job_fetch ON ${schema}.job (name, start_after) INCLUDE (priority, created_on, id) WHERE state < '${
|
|
255
|
+
return `CREATE INDEX job_fetch ON ${schema}.job (name, start_after) INCLUDE (priority, created_on, id) WHERE state < '${JOB_STATES.active}'`
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
function createTableArchive (schema) {
|
|
@@ -322,7 +322,7 @@ function deleteQueueRecords (schema) {
|
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
function purgeQueue (schema) {
|
|
325
|
-
return `DELETE from ${schema}.job WHERE name = $1 and state < '${
|
|
325
|
+
return `DELETE from ${schema}.job WHERE name = $1 and state < '${JOB_STATES.active}'`
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
function clearStorage (schema) {
|
|
@@ -330,8 +330,8 @@ function clearStorage (schema) {
|
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
function getQueueSize (schema, options = {}) {
|
|
333
|
-
options.before = options.before ||
|
|
334
|
-
assert(options.before in
|
|
333
|
+
options.before = options.before || JOB_STATES.active
|
|
334
|
+
assert(options.before in JOB_STATES, `${options.before} is not a valid state`)
|
|
335
335
|
return `SELECT count(*) as count FROM ${schema}.job WHERE name = $1 AND state < '${options.before}'`
|
|
336
336
|
}
|
|
337
337
|
|
|
@@ -456,14 +456,14 @@ function fetchNextJob (schema) {
|
|
|
456
456
|
SELECT id
|
|
457
457
|
FROM ${schema}.job
|
|
458
458
|
WHERE name = $1
|
|
459
|
-
AND state < '${
|
|
459
|
+
AND state < '${JOB_STATES.active}'
|
|
460
460
|
AND start_after < now()
|
|
461
461
|
ORDER BY ${priority && 'priority desc, '} created_on, id
|
|
462
462
|
LIMIT $2
|
|
463
463
|
FOR UPDATE SKIP LOCKED
|
|
464
464
|
)
|
|
465
465
|
UPDATE ${schema}.job j SET
|
|
466
|
-
state = '${
|
|
466
|
+
state = '${JOB_STATES.active}',
|
|
467
467
|
started_on = now(),
|
|
468
468
|
retry_count = CASE WHEN started_on IS NOT NULL THEN retry_count + 1 ELSE retry_count END
|
|
469
469
|
FROM next
|
|
@@ -477,11 +477,11 @@ function completeJobs (schema) {
|
|
|
477
477
|
WITH results AS (
|
|
478
478
|
UPDATE ${schema}.job
|
|
479
479
|
SET completed_on = now(),
|
|
480
|
-
state = '${
|
|
480
|
+
state = '${JOB_STATES.completed}',
|
|
481
481
|
output = $3::jsonb
|
|
482
482
|
WHERE name = $1
|
|
483
483
|
AND id IN (SELECT UNNEST($2::uuid[]))
|
|
484
|
-
AND state = '${
|
|
484
|
+
AND state = '${JOB_STATES.active}'
|
|
485
485
|
RETURNING *
|
|
486
486
|
)
|
|
487
487
|
SELECT COUNT(*) FROM results
|
|
@@ -489,14 +489,14 @@ function completeJobs (schema) {
|
|
|
489
489
|
}
|
|
490
490
|
|
|
491
491
|
function failJobsById (schema) {
|
|
492
|
-
const where = `name = $1 AND id IN (SELECT UNNEST($2::uuid[])) AND state < '${
|
|
492
|
+
const where = `name = $1 AND id IN (SELECT UNNEST($2::uuid[])) AND state < '${JOB_STATES.completed}'`
|
|
493
493
|
const output = '$3::jsonb'
|
|
494
494
|
|
|
495
495
|
return failJobs(schema, where, output)
|
|
496
496
|
}
|
|
497
497
|
|
|
498
498
|
function failJobsByTimeout (schema) {
|
|
499
|
-
const where = `state = '${
|
|
499
|
+
const where = `state = '${JOB_STATES.active}' AND (started_on + expire_in) < now()`
|
|
500
500
|
const output = '\'{ "value": { "message": "job failed by timeout in active state" } }\'::jsonb'
|
|
501
501
|
return failJobs(schema, where, output)
|
|
502
502
|
}
|
|
@@ -506,8 +506,8 @@ function failJobs (schema, where, output) {
|
|
|
506
506
|
WITH results AS (
|
|
507
507
|
UPDATE ${schema}.job SET
|
|
508
508
|
state = CASE
|
|
509
|
-
WHEN retry_count < retry_limit THEN '${
|
|
510
|
-
ELSE '${
|
|
509
|
+
WHEN retry_count < retry_limit THEN '${JOB_STATES.retry}'::${schema}.job_state
|
|
510
|
+
ELSE '${JOB_STATES.failed}'::${schema}.job_state
|
|
511
511
|
END,
|
|
512
512
|
completed_on = CASE
|
|
513
513
|
WHEN retry_count < retry_limit THEN NULL
|
|
@@ -533,7 +533,7 @@ function failJobs (schema, where, output) {
|
|
|
533
533
|
retry_limit,
|
|
534
534
|
keep_until + (keep_until - start_after)
|
|
535
535
|
FROM results
|
|
536
|
-
WHERE state = '${
|
|
536
|
+
WHERE state = '${JOB_STATES.failed}'
|
|
537
537
|
AND dead_letter IS NOT NULL
|
|
538
538
|
AND NOT name = dead_letter
|
|
539
539
|
)
|
|
@@ -546,10 +546,10 @@ function cancelJobs (schema) {
|
|
|
546
546
|
with results as (
|
|
547
547
|
UPDATE ${schema}.job
|
|
548
548
|
SET completed_on = now(),
|
|
549
|
-
state = '${
|
|
549
|
+
state = '${JOB_STATES.cancelled}'
|
|
550
550
|
WHERE name = $1
|
|
551
551
|
AND id IN (SELECT UNNEST($2::uuid[]))
|
|
552
|
-
AND state < '${
|
|
552
|
+
AND state < '${JOB_STATES.completed}'
|
|
553
553
|
RETURNING 1
|
|
554
554
|
)
|
|
555
555
|
SELECT COUNT(*) from results
|
|
@@ -561,7 +561,7 @@ function resumeJobs (schema) {
|
|
|
561
561
|
with results as (
|
|
562
562
|
UPDATE ${schema}.job
|
|
563
563
|
SET completed_on = NULL,
|
|
564
|
-
state = '${
|
|
564
|
+
state = '${JOB_STATES.created}'
|
|
565
565
|
WHERE name = $1
|
|
566
566
|
AND id IN (SELECT UNNEST($2::uuid[]))
|
|
567
567
|
RETURNING 1
|
|
@@ -731,9 +731,9 @@ function archive (schema, completedInterval, failedInterval = completedInterval)
|
|
|
731
731
|
return `
|
|
732
732
|
WITH archived_rows AS (
|
|
733
733
|
DELETE FROM ${schema}.job
|
|
734
|
-
WHERE (state <> '${
|
|
735
|
-
OR (state = '${
|
|
736
|
-
OR (state < '${
|
|
734
|
+
WHERE (state <> '${JOB_STATES.failed}' AND completed_on < (now() - interval '${completedInterval}'))
|
|
735
|
+
OR (state = '${JOB_STATES.failed}' AND completed_on < (now() - interval '${failedInterval}'))
|
|
736
|
+
OR (state < '${JOB_STATES.active}' AND keep_until < now())
|
|
737
737
|
RETURNING *
|
|
738
738
|
)
|
|
739
739
|
INSERT INTO ${schema}.archive (${columns})
|
package/types.d.ts
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { EventEmitter } from 'events'
|
|
2
2
|
|
|
3
3
|
declare namespace PgBoss {
|
|
4
|
+
|
|
5
|
+
type JobStates = {
|
|
6
|
+
created : 'created',
|
|
7
|
+
retry: 'retry',
|
|
8
|
+
active: 'active',
|
|
9
|
+
completed: 'completed',
|
|
10
|
+
cancelled: 'cancelled',
|
|
11
|
+
failed: 'failed'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type QueuePolicies = {
|
|
15
|
+
standard: 'standard'
|
|
16
|
+
short: 'short',
|
|
17
|
+
singleton: 'singleton',
|
|
18
|
+
stately: 'stately'
|
|
19
|
+
}
|
|
4
20
|
interface Db {
|
|
5
21
|
executeSql(text: string, values: any[]): Promise<{ rows: any[] }>;
|
|
6
22
|
}
|
|
@@ -275,6 +291,9 @@ declare class PgBoss extends EventEmitter {
|
|
|
275
291
|
static getRollbackPlans(schema: string): string;
|
|
276
292
|
static getRollbackPlans(): string;
|
|
277
293
|
|
|
294
|
+
static states: PgBoss.JobStates
|
|
295
|
+
static policies: PgBoss.QueuePolicies
|
|
296
|
+
|
|
278
297
|
on(event: "error", handler: (error: Error) => void): this;
|
|
279
298
|
off(event: "error", handler: (error: Error) => void): this;
|
|
280
299
|
|