pg-boss 10.0.0-beta4 → 10.0.0-beta6
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 +1 -5
- package/package.json +1 -1
- package/src/attorney.js +4 -4
- package/src/manager.js +2 -2
- package/src/plans.js +135 -119
- package/types.d.ts +18 -16
package/README.md
CHANGED
|
@@ -15,10 +15,6 @@ async function readme() {
|
|
|
15
15
|
|
|
16
16
|
const queue = 'readme-queue'
|
|
17
17
|
|
|
18
|
-
try {
|
|
19
|
-
await boss.createQueue(queue)
|
|
20
|
-
} catch {}
|
|
21
|
-
|
|
22
18
|
const id = await boss.send(queue, { arg1: 'read me' })
|
|
23
19
|
|
|
24
20
|
console.log(`created job ${id} in queue ${queue}`)
|
|
@@ -47,7 +43,7 @@ This will likely cater the most to teams already familiar with the simplicity of
|
|
|
47
43
|
|
|
48
44
|
## Requirements
|
|
49
45
|
* Node 20 or higher
|
|
50
|
-
* PostgreSQL
|
|
46
|
+
* PostgreSQL 13 or higher
|
|
51
47
|
|
|
52
48
|
## Installation
|
|
53
49
|
|
package/package.json
CHANGED
package/src/attorney.js
CHANGED
|
@@ -152,6 +152,10 @@ function getConfig (value) {
|
|
|
152
152
|
? { connectionString: value }
|
|
153
153
|
: { ...value }
|
|
154
154
|
|
|
155
|
+
config.schedule = ('schedule' in config) ? config.schedule : true
|
|
156
|
+
config.supervise = ('supervise' in config) ? config.supervise : true
|
|
157
|
+
config.migrate = ('migrate' in config) ? config.migrate : true
|
|
158
|
+
|
|
155
159
|
applySchemaConfig(config)
|
|
156
160
|
applyMaintenanceConfig(config)
|
|
157
161
|
applyArchiveConfig(config)
|
|
@@ -303,10 +307,6 @@ function applyMaintenanceConfig (config) {
|
|
|
303
307
|
: 120
|
|
304
308
|
|
|
305
309
|
assert(config.maintenanceIntervalSeconds / 60 / 60 < MAX_INTERVAL_HOURS, `configuration assert: maintenance interval cannot exceed ${MAX_INTERVAL_HOURS} hours`)
|
|
306
|
-
|
|
307
|
-
config.schedule = ('schedule' in config) ? config.schedule : true
|
|
308
|
-
config.supervise = ('supervise' in config) ? config.supervise : true
|
|
309
|
-
config.migrate = ('migrate' in config) ? config.migrate : true
|
|
310
310
|
}
|
|
311
311
|
|
|
312
312
|
function applyDeleteConfig (config) {
|
package/src/manager.js
CHANGED
|
@@ -217,7 +217,7 @@ class Manager extends EventEmitter {
|
|
|
217
217
|
this.emitWip(name)
|
|
218
218
|
|
|
219
219
|
if (batchSize) {
|
|
220
|
-
const maxExpiration = jobs.reduce((acc, i) => Math.max(acc, i.
|
|
220
|
+
const maxExpiration = jobs.reduce((acc, i) => Math.max(acc, i.expireInSeconds), 0)
|
|
221
221
|
|
|
222
222
|
await resolveWithinSeconds(Promise.all([callback(jobs)]), maxExpiration)
|
|
223
223
|
.then(() => this.complete(name, jobs.map(job => job.id)))
|
|
@@ -228,7 +228,7 @@ class Manager extends EventEmitter {
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
const allTeamPromise = pMap(jobs, job =>
|
|
231
|
-
resolveWithinSeconds(callback(job), job.
|
|
231
|
+
resolveWithinSeconds(callback(job), job.expireInSeconds)
|
|
232
232
|
.then(result => this.complete(name, job.id, result))
|
|
233
233
|
.catch(err => this.fail(name, job.id, err))
|
|
234
234
|
.then(() => refill ? onRefill() : null)
|
package/src/plans.js
CHANGED
|
@@ -146,26 +146,44 @@ function createTableJob (schema) {
|
|
|
146
146
|
priority integer not null default(0),
|
|
147
147
|
data jsonb,
|
|
148
148
|
state ${schema}.job_state not null default('${states.created}'),
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
149
|
+
retry_limit integer not null default(0),
|
|
150
|
+
retry_count integer not null default(0),
|
|
151
|
+
retry_delay integer not null default(0),
|
|
152
|
+
retry_backoff boolean not null default false,
|
|
153
|
+
start_after timestamp with time zone not null default now(),
|
|
154
|
+
started_on timestamp with time zone,
|
|
155
|
+
singleton_key text,
|
|
156
|
+
singleton_on timestamp without time zone,
|
|
157
|
+
expire_in interval not null default interval '15 minutes',
|
|
158
|
+
created_on timestamp with time zone not null default now(),
|
|
159
|
+
completed_on timestamp with time zone,
|
|
160
|
+
keep_until timestamp with time zone NOT NULL default now() + interval '14 days',
|
|
161
161
|
output jsonb,
|
|
162
|
-
|
|
162
|
+
dead_letter text,
|
|
163
163
|
policy text,
|
|
164
164
|
CONSTRAINT job_pkey PRIMARY KEY (name, id)
|
|
165
165
|
) PARTITION BY LIST (name)
|
|
166
166
|
`
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
const baseJobColumns = 'id, name, data, EXTRACT(epoch FROM expire_in) as "expireInSeconds"'
|
|
170
|
+
const allJobColumns = `${baseJobColumns}, policy, state, priority,
|
|
171
|
+
retry_limit as "retryLimit",
|
|
172
|
+
retry_count as "retryCount",
|
|
173
|
+
retry_delay as "retryDelay",
|
|
174
|
+
retry_backoff as "retryBackoff",
|
|
175
|
+
start_after as "startAfter",
|
|
176
|
+
started_on as "startedOn",
|
|
177
|
+
singleton_key as "singletonKey",
|
|
178
|
+
singleton_on as "singletonOn",
|
|
179
|
+
expire_in as "expireIn",
|
|
180
|
+
created_on as "createdOn",
|
|
181
|
+
completed_on as "completedOn",
|
|
182
|
+
keep_until as "keepUntil",
|
|
183
|
+
dead_letter as "deadLetter",
|
|
184
|
+
output
|
|
185
|
+
`
|
|
186
|
+
|
|
169
187
|
function createPartition (schema, name) {
|
|
170
188
|
return `SELECT ${schema}.create_partition('${name}');`
|
|
171
189
|
}
|
|
@@ -174,7 +192,7 @@ function getPartitionFunction (schema) {
|
|
|
174
192
|
return `
|
|
175
193
|
CREATE FUNCTION ${schema}.get_partition(queue_name text, out name text) AS
|
|
176
194
|
$$
|
|
177
|
-
SELECT '${schema}.job_' || encode(
|
|
195
|
+
SELECT '${schema}.job_' || encode(sha224(queue_name::bytea), 'hex');
|
|
178
196
|
$$
|
|
179
197
|
LANGUAGE SQL
|
|
180
198
|
IMMUTABLE
|
|
@@ -232,11 +250,11 @@ function createIndexJobPolicyStately (schema) {
|
|
|
232
250
|
}
|
|
233
251
|
|
|
234
252
|
function createIndexJobThrottleOn (schema) {
|
|
235
|
-
return `CREATE UNIQUE INDEX job_throttle_on ON ${schema}.job (name,
|
|
253
|
+
return `CREATE UNIQUE INDEX job_throttle_on ON ${schema}.job (name, singleton_on, COALESCE(singleton_key, '')) WHERE state <= '${states.completed}' AND singleton_on IS NOT NULL`
|
|
236
254
|
}
|
|
237
255
|
|
|
238
256
|
function createIndexJobThrottleKey (schema) {
|
|
239
|
-
return `CREATE UNIQUE INDEX job_throttle_key ON ${schema}.job (name,
|
|
257
|
+
return `CREATE UNIQUE INDEX job_throttle_key ON ${schema}.job (name, singleton_key) WHERE state <= '${states.completed}' AND singleton_on IS NULL`
|
|
240
258
|
}
|
|
241
259
|
|
|
242
260
|
function createIndexJobName (schema) {
|
|
@@ -244,7 +262,7 @@ function createIndexJobName (schema) {
|
|
|
244
262
|
}
|
|
245
263
|
|
|
246
264
|
function createIndexJobFetch (schema) {
|
|
247
|
-
return `CREATE INDEX job_fetch ON ${schema}.job (name,
|
|
265
|
+
return `CREATE INDEX job_fetch ON ${schema}.job (name, start_after) INCLUDE (priority, created_on, id) WHERE state < '${states.active}'`
|
|
248
266
|
}
|
|
249
267
|
|
|
250
268
|
function createTableArchive (schema) {
|
|
@@ -252,11 +270,11 @@ function createTableArchive (schema) {
|
|
|
252
270
|
}
|
|
253
271
|
|
|
254
272
|
function createColumnArchiveArchivedOn (schema) {
|
|
255
|
-
return `ALTER TABLE ${schema}.archive ADD
|
|
273
|
+
return `ALTER TABLE ${schema}.archive ADD archived_on timestamptz NOT NULL DEFAULT now()`
|
|
256
274
|
}
|
|
257
275
|
|
|
258
276
|
function createIndexArchiveArchivedOn (schema) {
|
|
259
|
-
return `CREATE INDEX
|
|
277
|
+
return `CREATE INDEX archive_archived_on_idx ON ${schema}.archive(archived_on)`
|
|
260
278
|
}
|
|
261
279
|
|
|
262
280
|
function createIndexArchiveName (schema) {
|
|
@@ -458,19 +476,18 @@ function fetchNextJob (schema) {
|
|
|
458
476
|
FROM ${schema}.job
|
|
459
477
|
WHERE name = $1
|
|
460
478
|
AND state < '${states.active}'
|
|
461
|
-
AND
|
|
462
|
-
ORDER BY ${priority && 'priority desc, '}
|
|
479
|
+
AND start_after < now()
|
|
480
|
+
ORDER BY ${priority && 'priority desc, '} created_on, id
|
|
463
481
|
LIMIT $2
|
|
464
482
|
FOR UPDATE SKIP LOCKED
|
|
465
483
|
)
|
|
466
484
|
UPDATE ${schema}.job j SET
|
|
467
485
|
state = '${states.active}',
|
|
468
|
-
|
|
469
|
-
|
|
486
|
+
started_on = now(),
|
|
487
|
+
retry_count = CASE WHEN started_on IS NOT NULL THEN retry_count + 1 ELSE retry_count END
|
|
470
488
|
FROM next
|
|
471
489
|
WHERE name = $1 AND j.id = next.id
|
|
472
|
-
RETURNING
|
|
473
|
-
EXTRACT(epoch FROM expireIn) as expire_in_seconds
|
|
490
|
+
RETURNING j.${includeMetadata ? allJobColumns : baseJobColumns}
|
|
474
491
|
`
|
|
475
492
|
}
|
|
476
493
|
|
|
@@ -478,7 +495,7 @@ function completeJobs (schema) {
|
|
|
478
495
|
return `
|
|
479
496
|
WITH results AS (
|
|
480
497
|
UPDATE ${schema}.job
|
|
481
|
-
SET
|
|
498
|
+
SET completed_on = now(),
|
|
482
499
|
state = '${states.completed}',
|
|
483
500
|
output = $3::jsonb
|
|
484
501
|
WHERE name = $1
|
|
@@ -498,7 +515,7 @@ function failJobsById (schema) {
|
|
|
498
515
|
}
|
|
499
516
|
|
|
500
517
|
function failJobsByTimeout (schema) {
|
|
501
|
-
const where = `state = '${states.active}' AND (
|
|
518
|
+
const where = `state = '${states.active}' AND (started_on + expire_in) < now()`
|
|
502
519
|
const output = '\'{ "value": { "message": "job failed by timeout in active state" } }\'::jsonb'
|
|
503
520
|
return failJobs(schema, where, output)
|
|
504
521
|
}
|
|
@@ -508,36 +525,36 @@ function failJobs (schema, where, output) {
|
|
|
508
525
|
WITH results AS (
|
|
509
526
|
UPDATE ${schema}.job SET
|
|
510
527
|
state = CASE
|
|
511
|
-
WHEN
|
|
528
|
+
WHEN retry_count < retry_limit THEN '${states.retry}'::${schema}.job_state
|
|
512
529
|
ELSE '${states.failed}'::${schema}.job_state
|
|
513
530
|
END,
|
|
514
|
-
|
|
515
|
-
WHEN
|
|
531
|
+
completed_on = CASE
|
|
532
|
+
WHEN retry_count < retry_limit THEN NULL
|
|
516
533
|
ELSE now()
|
|
517
534
|
END,
|
|
518
|
-
|
|
519
|
-
WHEN
|
|
520
|
-
WHEN NOT
|
|
535
|
+
start_after = CASE
|
|
536
|
+
WHEN retry_count = retry_limit THEN start_after
|
|
537
|
+
WHEN NOT retry_backoff THEN now() + retry_delay * interval '1'
|
|
521
538
|
ELSE now() + (
|
|
522
|
-
|
|
523
|
-
|
|
539
|
+
retry_delay * 2 ^ LEAST(16, retry_count + 1) / 2 +
|
|
540
|
+
retry_delay * 2 ^ LEAST(16, retry_count + 1) / 2 * random()
|
|
524
541
|
) * interval '1'
|
|
525
542
|
END,
|
|
526
543
|
output = ${output}
|
|
527
544
|
WHERE ${where}
|
|
528
545
|
RETURNING *
|
|
529
546
|
), dlq_jobs as (
|
|
530
|
-
INSERT INTO ${schema}.job (name, data, output,
|
|
547
|
+
INSERT INTO ${schema}.job (name, data, output, retry_limit, keep_until)
|
|
531
548
|
SELECT
|
|
532
|
-
|
|
549
|
+
dead_letter,
|
|
533
550
|
data,
|
|
534
551
|
output,
|
|
535
|
-
|
|
536
|
-
|
|
552
|
+
retry_limit,
|
|
553
|
+
keep_until + (keep_until - start_after)
|
|
537
554
|
FROM results
|
|
538
555
|
WHERE state = '${states.failed}'
|
|
539
|
-
AND
|
|
540
|
-
AND NOT name =
|
|
556
|
+
AND dead_letter IS NOT NULL
|
|
557
|
+
AND NOT name = dead_letter
|
|
541
558
|
)
|
|
542
559
|
SELECT COUNT(*) FROM results
|
|
543
560
|
`
|
|
@@ -547,7 +564,7 @@ function cancelJobs (schema) {
|
|
|
547
564
|
return `
|
|
548
565
|
with results as (
|
|
549
566
|
UPDATE ${schema}.job
|
|
550
|
-
SET
|
|
567
|
+
SET completed_on = now(),
|
|
551
568
|
state = '${states.cancelled}'
|
|
552
569
|
WHERE name = $1
|
|
553
570
|
AND id IN (SELECT UNNEST($2::uuid[]))
|
|
@@ -562,7 +579,7 @@ function resumeJobs (schema) {
|
|
|
562
579
|
return `
|
|
563
580
|
with results as (
|
|
564
581
|
UPDATE ${schema}.job
|
|
565
|
-
SET
|
|
582
|
+
SET completed_on = NULL,
|
|
566
583
|
state = '${states.created}'
|
|
567
584
|
WHERE name = $1
|
|
568
585
|
AND id IN (SELECT UNNEST($2::uuid[]))
|
|
@@ -579,15 +596,15 @@ function insertJob (schema) {
|
|
|
579
596
|
name,
|
|
580
597
|
data,
|
|
581
598
|
priority,
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
599
|
+
start_after,
|
|
600
|
+
singleton_key,
|
|
601
|
+
singleton_on,
|
|
602
|
+
dead_letter,
|
|
603
|
+
expire_in,
|
|
604
|
+
keep_until,
|
|
605
|
+
retry_limit,
|
|
606
|
+
retry_delay,
|
|
607
|
+
retry_backoff,
|
|
591
608
|
policy
|
|
592
609
|
)
|
|
593
610
|
SELECT
|
|
@@ -595,27 +612,27 @@ function insertJob (schema) {
|
|
|
595
612
|
j.name,
|
|
596
613
|
data,
|
|
597
614
|
priority,
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
COALESCE(
|
|
615
|
+
start_after,
|
|
616
|
+
singleton_key,
|
|
617
|
+
singleton_on,
|
|
618
|
+
COALESCE(j.dead_letter, q.dead_letter) as dead_letter,
|
|
602
619
|
CASE
|
|
603
|
-
WHEN
|
|
620
|
+
WHEN expire_in IS NOT NULL THEN CAST(expire_in as interval)
|
|
604
621
|
WHEN q.expire_seconds IS NOT NULL THEN q.expire_seconds * interval '1s'
|
|
605
|
-
WHEN
|
|
622
|
+
WHEN expire_in_default IS NOT NULL THEN CAST(expire_in_default as interval)
|
|
606
623
|
ELSE interval '15 minutes'
|
|
607
|
-
END as
|
|
624
|
+
END as expire_in,
|
|
608
625
|
CASE
|
|
609
|
-
WHEN right(
|
|
610
|
-
ELSE
|
|
611
|
-
END as
|
|
612
|
-
COALESCE(
|
|
626
|
+
WHEN right(keep_until, 1) = 'Z' THEN CAST(keep_until as timestamp with time zone)
|
|
627
|
+
ELSE start_after + CAST(COALESCE(keep_until, (q.retention_minutes * 60)::text, keep_until_default, '14 days') as interval)
|
|
628
|
+
END as keep_until,
|
|
629
|
+
COALESCE(j.retry_limit, q.retry_limit, retry_limit_default, 2) as retry_limit,
|
|
613
630
|
CASE
|
|
614
|
-
WHEN COALESCE(
|
|
615
|
-
THEN GREATEST(COALESCE(
|
|
616
|
-
ELSE COALESCE(
|
|
617
|
-
END as
|
|
618
|
-
COALESCE(
|
|
631
|
+
WHEN COALESCE(j.retry_backoff, q.retry_backoff, retry_backoff_default, false)
|
|
632
|
+
THEN GREATEST(COALESCE(j.retry_delay, q.retry_delay, retry_delay_default), 1)
|
|
633
|
+
ELSE COALESCE(j.retry_delay, q.retry_delay, retry_delay_default, 0)
|
|
634
|
+
END as retry_delay,
|
|
635
|
+
COALESCE(j.retry_backoff, q.retry_backoff, retry_backoff_default, false) as retry_backoff,
|
|
619
636
|
q.policy
|
|
620
637
|
FROM
|
|
621
638
|
( SELECT
|
|
@@ -626,23 +643,23 @@ function insertJob (schema) {
|
|
|
626
643
|
CASE
|
|
627
644
|
WHEN right($5, 1) = 'Z' THEN CAST($5 as timestamp with time zone)
|
|
628
645
|
ELSE now() + CAST(COALESCE($5,'0') as interval)
|
|
629
|
-
END as
|
|
630
|
-
$6 as
|
|
646
|
+
END as start_after,
|
|
647
|
+
$6 as singleton_key,
|
|
631
648
|
CASE
|
|
632
649
|
WHEN $7::integer IS NOT NULL THEN 'epoch'::timestamp + '1 second'::interval * ($7 * floor((date_part('epoch', now()) + $8) / $7))
|
|
633
650
|
ELSE NULL
|
|
634
|
-
END as
|
|
635
|
-
$9 as
|
|
636
|
-
$10 as
|
|
637
|
-
$11 as
|
|
638
|
-
$12 as
|
|
639
|
-
$13 as
|
|
640
|
-
$14::int as
|
|
641
|
-
$15::int as
|
|
642
|
-
$16::int as
|
|
643
|
-
$17::int as
|
|
644
|
-
$18::bool as
|
|
645
|
-
$19::bool as
|
|
651
|
+
END as singleton_on,
|
|
652
|
+
$9 as dead_letter,
|
|
653
|
+
$10 as expire_in,
|
|
654
|
+
$11 as expire_in_default,
|
|
655
|
+
$12 as keep_until,
|
|
656
|
+
$13 as keep_until_default,
|
|
657
|
+
$14::int as retry_limit,
|
|
658
|
+
$15::int as retry_limit_default,
|
|
659
|
+
$16::int as retry_delay,
|
|
660
|
+
$17::int as retry_delay_default,
|
|
661
|
+
$18::bool as retry_backoff,
|
|
662
|
+
$19::bool as retry_backoff_default
|
|
646
663
|
) j LEFT JOIN ${schema}.queue q ON j.name = q.name
|
|
647
664
|
ON CONFLICT DO NOTHING
|
|
648
665
|
RETURNING id
|
|
@@ -653,25 +670,25 @@ function insertJobs (schema) {
|
|
|
653
670
|
return `
|
|
654
671
|
WITH defaults as (
|
|
655
672
|
SELECT
|
|
656
|
-
$2 as
|
|
657
|
-
$3 as
|
|
658
|
-
$4::int as
|
|
659
|
-
$5::int as
|
|
660
|
-
$6::bool as
|
|
673
|
+
$2 as expire_in,
|
|
674
|
+
$3 as keep_until,
|
|
675
|
+
$4::int as retry_limit,
|
|
676
|
+
$5::int as retry_delay,
|
|
677
|
+
$6::bool as retry_backoff
|
|
661
678
|
)
|
|
662
679
|
INSERT INTO ${schema}.job (
|
|
663
680
|
id,
|
|
664
681
|
name,
|
|
665
682
|
data,
|
|
666
683
|
priority,
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
684
|
+
start_after,
|
|
685
|
+
singleton_key,
|
|
686
|
+
dead_letter,
|
|
687
|
+
expire_in,
|
|
688
|
+
keep_until,
|
|
689
|
+
retry_limit,
|
|
690
|
+
retry_delay,
|
|
691
|
+
retry_backoff,
|
|
675
692
|
policy
|
|
676
693
|
)
|
|
677
694
|
SELECT
|
|
@@ -685,20 +702,20 @@ function insertJobs (schema) {
|
|
|
685
702
|
CASE
|
|
686
703
|
WHEN "expireInSeconds" IS NOT NULL THEN "expireInSeconds" * interval '1s'
|
|
687
704
|
WHEN q.expire_seconds IS NOT NULL THEN q.expire_seconds * interval '1s'
|
|
688
|
-
WHEN defaults.
|
|
705
|
+
WHEN defaults.expire_in IS NOT NULL THEN CAST(defaults.expire_in as interval)
|
|
689
706
|
ELSE interval '15 minutes'
|
|
690
|
-
END as
|
|
707
|
+
END as expire_in,
|
|
691
708
|
CASE
|
|
692
709
|
WHEN "keepUntil" IS NOT NULL THEN "keepUntil"
|
|
693
|
-
ELSE COALESCE("startAfter", now()) + CAST(COALESCE((q.retention_minutes * 60)::text, defaults.
|
|
694
|
-
END as
|
|
695
|
-
COALESCE("retryLimit", q.retry_limit, defaults.
|
|
710
|
+
ELSE COALESCE("startAfter", now()) + CAST(COALESCE((q.retention_minutes * 60)::text, defaults.keep_until, '14 days') as interval)
|
|
711
|
+
END as keep_until,
|
|
712
|
+
COALESCE("retryLimit", q.retry_limit, defaults.retry_limit, 2),
|
|
696
713
|
CASE
|
|
697
|
-
WHEN COALESCE("retryBackoff", q.retry_backoff, defaults.
|
|
698
|
-
THEN GREATEST(COALESCE("retryDelay", q.retry_delay, defaults.
|
|
699
|
-
ELSE COALESCE("retryDelay", q.retry_delay, defaults.
|
|
700
|
-
END as
|
|
701
|
-
COALESCE("retryBackoff", q.retry_backoff, defaults.
|
|
714
|
+
WHEN COALESCE("retryBackoff", q.retry_backoff, defaults.retry_backoff, false)
|
|
715
|
+
THEN GREATEST(COALESCE("retryDelay", q.retry_delay, defaults.retry_delay), 1)
|
|
716
|
+
ELSE COALESCE("retryDelay", q.retry_delay, defaults.retry_delay, 0)
|
|
717
|
+
END as retry_delay,
|
|
718
|
+
COALESCE("retryBackoff", q.retry_backoff, defaults.retry_backoff, false) as retry_backoff,
|
|
702
719
|
q.policy
|
|
703
720
|
FROM json_to_recordset($1) as j (
|
|
704
721
|
id uuid,
|
|
@@ -723,24 +740,23 @@ function insertJobs (schema) {
|
|
|
723
740
|
function drop (schema, interval) {
|
|
724
741
|
return `
|
|
725
742
|
DELETE FROM ${schema}.archive
|
|
726
|
-
WHERE
|
|
743
|
+
WHERE archived_on < (now() - interval '${interval}')
|
|
727
744
|
`
|
|
728
745
|
}
|
|
729
746
|
|
|
730
747
|
function archive (schema, completedInterval, failedInterval = completedInterval) {
|
|
748
|
+
const columns = 'id, name, priority, data, state, retry_limit, retry_count, retry_delay, retry_backoff, start_after, started_on, singleton_key, singleton_on, expire_in, created_on, completed_on, keep_until, dead_letter, policy, output'
|
|
749
|
+
|
|
731
750
|
return `
|
|
732
751
|
WITH archived_rows AS (
|
|
733
752
|
DELETE FROM ${schema}.job
|
|
734
|
-
WHERE (state <> '${states.failed}' AND
|
|
735
|
-
OR (state = '${states.failed}' AND
|
|
736
|
-
OR (state < '${states.active}' AND
|
|
753
|
+
WHERE (state <> '${states.failed}' AND completed_on < (now() - interval '${completedInterval}'))
|
|
754
|
+
OR (state = '${states.failed}' AND completed_on < (now() - interval '${failedInterval}'))
|
|
755
|
+
OR (state < '${states.active}' AND keep_until < now())
|
|
737
756
|
RETURNING *
|
|
738
757
|
)
|
|
739
|
-
INSERT INTO ${schema}.archive (
|
|
740
|
-
|
|
741
|
-
)
|
|
742
|
-
SELECT
|
|
743
|
-
id, name, priority, data, state, retryLimit, retryCount, retryDelay, retryBackoff, startAfter, startedOn, singletonKey, singletonOn, expireIn, createdOn, completedOn, keepUntil, deadletter, policy, output
|
|
758
|
+
INSERT INTO ${schema}.archive (${columns})
|
|
759
|
+
SELECT ${columns}
|
|
744
760
|
FROM archived_rows
|
|
745
761
|
`
|
|
746
762
|
}
|
|
@@ -769,7 +785,7 @@ function locked (schema, query) {
|
|
|
769
785
|
|
|
770
786
|
function advisoryLock (schema, key) {
|
|
771
787
|
return `SELECT pg_advisory_xact_lock(
|
|
772
|
-
('x' || encode(
|
|
788
|
+
('x' || encode(sha224((current_database() || '.pgboss.${schema}${key || ''}')::bytea), 'hex'))::bit(64)::bigint
|
|
773
789
|
)`
|
|
774
790
|
}
|
|
775
791
|
|
|
@@ -779,13 +795,13 @@ function assertMigration (schema, version) {
|
|
|
779
795
|
}
|
|
780
796
|
|
|
781
797
|
function getJobById (schema) {
|
|
782
|
-
return
|
|
798
|
+
return getJobByTableQueueId(schema, 'job')
|
|
783
799
|
}
|
|
784
800
|
|
|
785
801
|
function getArchivedJobById (schema) {
|
|
786
|
-
return
|
|
802
|
+
return getJobByTableQueueId(schema, 'archive')
|
|
787
803
|
}
|
|
788
804
|
|
|
789
|
-
function
|
|
790
|
-
return `SELECT
|
|
805
|
+
function getJobByTableQueueId (schema, table) {
|
|
806
|
+
return `SELECT ${allJobColumns} FROM ${schema}.${table} WHERE name = $1 AND id = $2`
|
|
791
807
|
}
|
package/types.d.ts
CHANGED
|
@@ -176,24 +176,26 @@ declare namespace PgBoss {
|
|
|
176
176
|
data: T;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
interface JobWithMetadata<T = object>
|
|
179
|
+
interface JobWithMetadata<T = object> {
|
|
180
|
+
id: string;
|
|
181
|
+
name: string;
|
|
182
|
+
data: T;
|
|
180
183
|
priority: number;
|
|
181
184
|
state: 'created' | 'retry' | 'active' | 'completed' | 'cancelled' | 'failed';
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
deadletter: string,
|
|
185
|
+
retryLimit: number;
|
|
186
|
+
retryCount: number;
|
|
187
|
+
retryDelay: number;
|
|
188
|
+
retryBackoff: boolean;
|
|
189
|
+
startAfter: Date;
|
|
190
|
+
startedOn: Date;
|
|
191
|
+
singletonKey: string | null;
|
|
192
|
+
singletonOn: Date | null;
|
|
193
|
+
expireIn: PostgresInterval;
|
|
194
|
+
createdOn: Date;
|
|
195
|
+
completedOn: Date | null;
|
|
196
|
+
keepUntil: Date;
|
|
197
|
+
deadLetter: string,
|
|
198
|
+
policy: string,
|
|
197
199
|
output: object
|
|
198
200
|
}
|
|
199
201
|
|