pg-boss 10.1.5 → 10.2.0
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 +7 -1
- package/docker-compose.yaml +15 -0
- package/package.json +5 -5
- package/src/attorney.js +1 -0
- package/src/plans.js +13 -13
- package/src/timekeeper.js +1 -1
package/README.md
CHANGED
|
@@ -82,4 +82,10 @@ To run the test suite, linter and code coverage:
|
|
|
82
82
|
npm run cover
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
The test suite will try and create a new database named pgboss. The [config.json](test/config.json) file has the default credentials to connect to postgres.
|
|
85
|
+
The test suite will try and create a new database named pgboss. The [config.json](test/config.json) file has the default credentials to connect to postgres.
|
|
86
|
+
|
|
87
|
+
The [Docker Compose](docker-compose.yaml) file can be used to start a local postgres instance for testing:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
docker-compose up -d
|
|
91
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
services:
|
|
2
|
+
db:
|
|
3
|
+
image: postgres:16
|
|
4
|
+
ports:
|
|
5
|
+
- 5432:5432
|
|
6
|
+
volumes:
|
|
7
|
+
- db_volume:/var/lib/postgresql/data
|
|
8
|
+
environment:
|
|
9
|
+
- POSTGRES_DB=pgboss
|
|
10
|
+
- POSTGRES_NAME=pgboss
|
|
11
|
+
- POSTGRES_USER=postgres
|
|
12
|
+
- POSTGRES_PASSWORD=postgres
|
|
13
|
+
|
|
14
|
+
volumes:
|
|
15
|
+
db_volume:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pg-boss",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.2.0",
|
|
4
4
|
"description": "Queueing jobs in Postgres from Node.js like a boss",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"cron-parser": "^4.9.0",
|
|
11
|
-
"pg": "^8.
|
|
11
|
+
"pg": "^8.14.1",
|
|
12
12
|
"serialize-error": "^8.1.0"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@types/node": "^20.
|
|
16
|
-
"luxon": "^3.
|
|
17
|
-
"mocha": "^10.
|
|
15
|
+
"@types/node": "^20.17.30",
|
|
16
|
+
"luxon": "^3.6.1",
|
|
17
|
+
"mocha": "^10.8.2",
|
|
18
18
|
"nyc": "^17.1.0",
|
|
19
19
|
"standard": "^17.1.2"
|
|
20
20
|
},
|
package/src/attorney.js
CHANGED
|
@@ -143,6 +143,7 @@ function checkFetchArgs (name, options) {
|
|
|
143
143
|
assert(!('batchSize' in options) || (Number.isInteger(options.batchSize) && options.batchSize >= 1), 'batchSize must be an integer > 0')
|
|
144
144
|
assert(!('includeMetadata' in options) || typeof options.includeMetadata === 'boolean', 'includeMetadata must be a boolean')
|
|
145
145
|
assert(!('priority' in options) || typeof options.priority === 'boolean', 'priority must be a boolean')
|
|
146
|
+
assert(!('ignoreStartAfter' in options) || typeof options.ignoreStartAfter === 'boolean', 'ignoreStartAfter must be a boolean')
|
|
146
147
|
|
|
147
148
|
options.batchSize = options.batchSize || 1
|
|
148
149
|
}
|
package/src/plans.js
CHANGED
|
@@ -140,7 +140,7 @@ function createTableQueue (schema) {
|
|
|
140
140
|
partition_name text,
|
|
141
141
|
created_on timestamp with time zone not null default now(),
|
|
142
142
|
updated_on timestamp with time zone not null default now(),
|
|
143
|
-
PRIMARY KEY (name)
|
|
143
|
+
PRIMARY KEY (name)
|
|
144
144
|
)
|
|
145
145
|
`
|
|
146
146
|
}
|
|
@@ -208,7 +208,7 @@ const allJobColumns = `${baseJobColumns},
|
|
|
208
208
|
retry_count as "retryCount",
|
|
209
209
|
retry_delay as "retryDelay",
|
|
210
210
|
retry_backoff as "retryBackoff",
|
|
211
|
-
start_after as "startAfter",
|
|
211
|
+
start_after as "startAfter",
|
|
212
212
|
started_on as "startedOn",
|
|
213
213
|
singleton_key as "singletonKey",
|
|
214
214
|
singleton_on as "singletonOn",
|
|
@@ -263,7 +263,7 @@ function createQueueFunction (schema) {
|
|
|
263
263
|
END IF;
|
|
264
264
|
|
|
265
265
|
EXECUTE format('CREATE TABLE ${schema}.%I (LIKE ${schema}.job INCLUDING DEFAULTS)', table_name);
|
|
266
|
-
|
|
266
|
+
|
|
267
267
|
EXECUTE format('${formatPartitionCommand(createPrimaryKeyJob(schema))}', table_name);
|
|
268
268
|
EXECUTE format('${formatPartitionCommand(createQueueForeignKeyJob(schema))}', table_name);
|
|
269
269
|
EXECUTE format('${formatPartitionCommand(createQueueForeignKeyJobDeadLetter(schema))}', table_name);
|
|
@@ -292,7 +292,7 @@ function deleteQueueFunction (schema) {
|
|
|
292
292
|
$$
|
|
293
293
|
DECLARE
|
|
294
294
|
table_name varchar;
|
|
295
|
-
BEGIN
|
|
295
|
+
BEGIN
|
|
296
296
|
WITH deleted as (
|
|
297
297
|
DELETE FROM ${schema}.queue
|
|
298
298
|
WHERE name = queue_name
|
|
@@ -400,7 +400,7 @@ function updateQueue (schema) {
|
|
|
400
400
|
|
|
401
401
|
function getQueues (schema) {
|
|
402
402
|
return `
|
|
403
|
-
SELECT
|
|
403
|
+
SELECT
|
|
404
404
|
name,
|
|
405
405
|
policy,
|
|
406
406
|
retry_limit as "retryLimit",
|
|
@@ -503,13 +503,13 @@ function insertVersion (schema, version) {
|
|
|
503
503
|
}
|
|
504
504
|
|
|
505
505
|
function fetchNextJob (schema) {
|
|
506
|
-
return ({ includeMetadata, priority = true } = {}) => `
|
|
506
|
+
return ({ includeMetadata, priority = true, ignoreStartAfter = false } = {}) => `
|
|
507
507
|
WITH next as (
|
|
508
508
|
SELECT id
|
|
509
509
|
FROM ${schema}.job
|
|
510
510
|
WHERE name = $1
|
|
511
511
|
AND state < '${JOB_STATES.active}'
|
|
512
|
-
AND start_after < now()
|
|
512
|
+
${ignoreStartAfter ? '' : 'AND start_after < now()'}
|
|
513
513
|
ORDER BY ${priority ? 'priority desc, ' : ''}created_on, id
|
|
514
514
|
LIMIT $2
|
|
515
515
|
FOR UPDATE SKIP LOCKED
|
|
@@ -520,7 +520,7 @@ function fetchNextJob (schema) {
|
|
|
520
520
|
retry_count = CASE WHEN started_on IS NOT NULL THEN retry_count + 1 ELSE retry_count END
|
|
521
521
|
FROM next
|
|
522
522
|
WHERE name = $1 AND j.id = next.id
|
|
523
|
-
RETURNING j.${includeMetadata ? allJobColumns : baseJobColumns}
|
|
523
|
+
RETURNING j.${includeMetadata ? allJobColumns : baseJobColumns}
|
|
524
524
|
`
|
|
525
525
|
}
|
|
526
526
|
|
|
@@ -615,7 +615,7 @@ function failJobs (schema, where, output) {
|
|
|
615
615
|
END as completed_on,
|
|
616
616
|
keep_until,
|
|
617
617
|
dead_letter,
|
|
618
|
-
policy,
|
|
618
|
+
policy,
|
|
619
619
|
${output}
|
|
620
620
|
FROM deleted_jobs
|
|
621
621
|
ON CONFLICT DO NOTHING
|
|
@@ -726,7 +726,7 @@ function deleteJobs (schema) {
|
|
|
726
726
|
with results as (
|
|
727
727
|
DELETE FROM ${schema}.job
|
|
728
728
|
WHERE name = $1
|
|
729
|
-
AND id IN (SELECT UNNEST($2::uuid[]))
|
|
729
|
+
AND id IN (SELECT UNNEST($2::uuid[]))
|
|
730
730
|
RETURNING 1
|
|
731
731
|
)
|
|
732
732
|
SELECT COUNT(*) from results
|
|
@@ -813,7 +813,7 @@ function insertJob (schema) {
|
|
|
813
813
|
function insertJobs (schema) {
|
|
814
814
|
return `
|
|
815
815
|
WITH defaults as (
|
|
816
|
-
SELECT
|
|
816
|
+
SELECT
|
|
817
817
|
$2 as expire_in,
|
|
818
818
|
$3 as keep_until,
|
|
819
819
|
$4::int as retry_limit,
|
|
@@ -863,7 +863,7 @@ function insertJobs (schema) {
|
|
|
863
863
|
WHEN COALESCE("retryBackoff", q.retry_backoff, defaults.retry_backoff, false)
|
|
864
864
|
THEN GREATEST(COALESCE("retryDelay", q.retry_delay, defaults.retry_delay), 1)
|
|
865
865
|
ELSE COALESCE("retryDelay", q.retry_delay, defaults.retry_delay, 0)
|
|
866
|
-
END as retry_delay,
|
|
866
|
+
END as retry_delay,
|
|
867
867
|
COALESCE("retryBackoff", q.retry_backoff, defaults.retry_backoff, false) as retry_backoff,
|
|
868
868
|
q.policy
|
|
869
869
|
FROM (
|
|
@@ -886,7 +886,7 @@ function insertJobs (schema) {
|
|
|
886
886
|
"expireInSeconds" integer,
|
|
887
887
|
"keepUntil" timestamp with time zone,
|
|
888
888
|
"deadLetter" text
|
|
889
|
-
)
|
|
889
|
+
)
|
|
890
890
|
) j
|
|
891
891
|
JOIN ${schema}.queue q ON j.name = q.name,
|
|
892
892
|
defaults
|
package/src/timekeeper.js
CHANGED
|
@@ -144,7 +144,7 @@ class Timekeeper extends EventEmitter {
|
|
|
144
144
|
const scheduled = schedules
|
|
145
145
|
.filter(i => this.shouldSendIt(i.cron, i.timezone))
|
|
146
146
|
.map(({ name, data, options }) =>
|
|
147
|
-
({ name: QUEUES.SEND_IT, data: { name, data, options }, singletonKey: name, singletonSeconds: 60 }))
|
|
147
|
+
({ name: QUEUES.SEND_IT, data: { name, data, ...options }, singletonKey: name, singletonSeconds: 60 }))
|
|
148
148
|
|
|
149
149
|
if (scheduled.length > 0 && !this.stopped) {
|
|
150
150
|
await this.manager.insert(scheduled)
|