From 035a66a70f715f1723dd420e5391bdab40269043 Mon Sep 17 00:00:00 2001 From: Kyriakos Lesgidis Date: Sat, 28 Jan 2023 19:54:50 +0200 Subject: [PATCH 1/8] Add archiveFailedAfterSeconds option --- docs/readme.md | 9 ++++++++- src/attorney.js | 15 +++++++++++++++ src/boss.js | 2 +- src/plans.js | 12 ++++++++---- src/timekeeper.js | 2 +- test/archiveTest.js | 38 ++++++++++++++++++++++++++++++++++++++ types.d.ts | 1 + 7 files changed, 72 insertions(+), 7 deletions(-) diff --git a/docs/readme.md b/docs/readme.md index b39617ea..74433e67 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -77,7 +77,8 @@ Architecturally, pg-boss is somewhat similar to queue products such as AWS SQS, All jobs start out in the `created` state and become `active` when picked up for work. If job processing completes successfully, jobs will go to `completed`. If a job fails, it will typcially enter the `failed` state. However, if a job has retry options configured, it will enter the `retry` state on failure instead and have a chance to re-enter `active` state. It's also possible for `active` jobs to become `expired`, which happens when job processing takes too long. Jobs can also enter `cancelled` state via [`cancel(id)`](#cancelid) or [`cancel([ids])`](#cancelids). -All jobs that are `completed`, `expired`, `cancelled` or `failed` become eligible for archiving (i.e. they will transition into the `archive` state) after the configured `archiveCompletedAfterSeconds` time. Once `archive`d, jobs will be automatically deleted by pg-boss after the configured deletion period. +All jobs that are `completed`, `expired` or `cancelled` become eligible for archiving (i.e. they will transition into the `archive` state) after the configured `archiveCompletedAfterSeconds` time. The `failed` jobs become eligible for archiving after the configured `archiveFailedAfterSeconds` time. +Once `archive`d, jobs will be automatically deleted by pg-boss after the configured deletion period. Here's a state diagram that shows the possible states and their transitions: @@ -343,6 +344,12 @@ Queue options contain the following constructor-only settings. Default: 12 hours +* **archiveFailedAfterSeconds** + + Specifies how long in seconds failed jobs get archived. Note: a warning will be emitted if set to lower than 60s and cron processing will be disabled. + + Default: 7 days + **Monitoring options** * **monitorStateIntervalSeconds** - int, default undefined diff --git a/src/attorney.js b/src/attorney.js index 6ad64dcb..21e32195 100644 --- a/src/attorney.js +++ b/src/attorney.js @@ -159,6 +159,7 @@ function getConfig (value) { applyDatabaseConfig(config) applyMaintenanceConfig(config) applyArchiveConfig(config) + applyArchiveFailedConfig(config) applyDeleteConfig(config) applyMonitoringConfig(config) applyUuidConfig(config) @@ -195,6 +196,20 @@ function applyArchiveConfig (config) { } } +function applyArchiveFailedConfig (config) { + const ARCHIVE_DEFAULT = 60 * 60 * 24 * 7 + + assert(!('archiveFailedAfterSeconds' in config) || config.archiveFailedAfterSeconds >= 1, + 'configuration assert: archiveFailedAfterSeconds must be at least every second and less than ') + + config.archiveFailedSeconds = config.archiveFailedAfterSeconds || ARCHIVE_DEFAULT + config.archiveFailedInterval = `${config.archiveFailedSeconds} seconds` + + if (config.archiveSeconds < 60) { + emitWarning(WARNINGS.CRON_DISABLED) + } +} + function applyCompletionConfig (config, defaults) { assert(!('onComplete' in config) || config.onComplete === true || config.onComplete === false, 'configuration assert: onComplete must be either true or false') diff --git a/src/boss.js b/src/boss.js index cb85eac0..899f323b 100644 --- a/src/boss.js +++ b/src/boss.js @@ -33,7 +33,7 @@ class Boss extends EventEmitter { this.events = events this.expireCommand = plans.locked(config.schema, plans.expire(config.schema)) - this.archiveCommand = plans.locked(config.schema, plans.archive(config.schema, config.archiveInterval)) + this.archiveCommand = plans.locked(config.schema, plans.archive(config.schema, config.archiveInterval, config.archiveFailedInterval)) this.purgeCommand = plans.locked(config.schema, plans.purge(config.schema, config.deleteAfter)) this.getMaintenanceTimeCommand = plans.getMaintenanceTime(config.schema) this.setMaintenanceTimeCommand = plans.setMaintenanceTime(config.schema) diff --git a/src/plans.js b/src/plans.js index 774c0b50..bb7b2760 100644 --- a/src/plans.js +++ b/src/plans.js @@ -601,7 +601,7 @@ function insertJobs (schema) { keepUntil, on_complete ) - SELECT + SELECT COALESCE(id, gen_random_uuid()) as id, name, data, @@ -639,12 +639,16 @@ function purge (schema, interval) { ` } -function archive (schema, interval) { +function archive (schema, completedInterval, failedInterval = completedInterval) { return ` WITH archived_rows AS ( DELETE FROM ${schema}.job - WHERE - completedOn < (now() - interval '${interval}') + WHERE ( + state <> '${states.failed}' AND completedOn < (now() - interval '${completedInterval}') + ) + OR ( + state = '${states.failed}' AND completedOn < (now() - interval '${failedInterval}') + ) OR ( state < '${states.active}' AND keepUntil < now() ) diff --git a/src/timekeeper.js b/src/timekeeper.js index b9503f3e..a4161646 100644 --- a/src/timekeeper.js +++ b/src/timekeeper.js @@ -45,7 +45,7 @@ class Timekeeper extends EventEmitter { async start () { // setting the archive config too low breaks the cron 60s debounce interval so don't even try - if (this.config.archiveSeconds < 60) { + if (this.config.archiveSeconds < 60 || this.config.archiveFailedSeconds < 60) { return } diff --git a/test/archiveTest.js b/test/archiveTest.js index a43bd411..96700ea9 100644 --- a/test/archiveTest.js +++ b/test/archiveTest.js @@ -1,10 +1,12 @@ const assert = require('assert') const helper = require('./testHelper') const delay = require('delay') +const { states } = require('../src/plans') describe('archive', function () { const defaults = { archiveCompletedAfterSeconds: 1, + archiveFailedAfterSeconds: 10, maintenanceIntervalSeconds: 1 } @@ -80,4 +82,40 @@ describe('archive', function () { assert.strictEqual(jobId, archivedJob.id) assert.strictEqual(queue, archivedJob.name) }) + + it('should not archive a failed job before the config setting', async function () { + const config = { ...this.test.bossConfig, ...defaults } + const boss = this.test.boss = await helper.start(config) + + const queue = 'archive-failed' + + const failPayload = { someReason: 'nuna' } + const jobId = await boss.send(queue, null, { retentionSeconds: 1 }) + + await boss.fail(jobId, failPayload) + await delay(7000) + + const archivedJob = await helper.getArchivedJobById(config.schema, jobId) + + assert.strictEqual(archivedJob, null) + }) + + it('should archive a failed job', async function () { + const config = { ...this.test.bossConfig, ...defaults, archiveFailedAfterSeconds: 1 } + const boss = this.test.boss = await helper.start(config) + + const queue = 'archive-failed' + + const failPayload = { someReason: 'nuna' } + const jobId = await boss.send(queue, null, { retentionSeconds: 1 }) + + await boss.fail(jobId, failPayload) + await delay(7000) + + const archivedJob = await helper.getArchivedJobById(config.schema, jobId) + + assert.strictEqual(jobId, archivedJob.id) + assert.strictEqual(queue, archivedJob.name) + assert.strictEqual(states.failed, archivedJob.state) + }) }) diff --git a/types.d.ts b/types.d.ts index 49546a93..714d74e4 100644 --- a/types.d.ts +++ b/types.d.ts @@ -44,6 +44,7 @@ declare namespace PgBoss { maintenanceIntervalMinutes?: number; archiveCompletedAfterSeconds?: number; + archiveFailedAfterSeconds?: number; } type ConstructorOptions = From e31d4adf1ca90af85b1386dfb79381b95dfaf189 Mon Sep 17 00:00:00 2001 From: Kyriakos Lesgidis Date: Sat, 28 Jan 2023 19:57:52 +0200 Subject: [PATCH 2/8] Fix option --- src/attorney.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attorney.js b/src/attorney.js index 21e32195..291b9d72 100644 --- a/src/attorney.js +++ b/src/attorney.js @@ -205,7 +205,7 @@ function applyArchiveFailedConfig (config) { config.archiveFailedSeconds = config.archiveFailedAfterSeconds || ARCHIVE_DEFAULT config.archiveFailedInterval = `${config.archiveFailedSeconds} seconds` - if (config.archiveSeconds < 60) { + if (config.archiveFailedSeconds < 60) { emitWarning(WARNINGS.CRON_DISABLED) } } From b944f9ac2c4c6ed2851f24429e02fa15a86c78f8 Mon Sep 17 00:00:00 2001 From: Kyriakos Lesgidis Date: Mon, 30 Jan 2023 11:13:54 +0200 Subject: [PATCH 3/8] Update readme & defaults --- docs/readme.md | 5 ++--- src/attorney.js | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/readme.md b/docs/readme.md index 74433e67..46f61dec 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -77,8 +77,7 @@ Architecturally, pg-boss is somewhat similar to queue products such as AWS SQS, All jobs start out in the `created` state and become `active` when picked up for work. If job processing completes successfully, jobs will go to `completed`. If a job fails, it will typcially enter the `failed` state. However, if a job has retry options configured, it will enter the `retry` state on failure instead and have a chance to re-enter `active` state. It's also possible for `active` jobs to become `expired`, which happens when job processing takes too long. Jobs can also enter `cancelled` state via [`cancel(id)`](#cancelid) or [`cancel([ids])`](#cancelids). -All jobs that are `completed`, `expired` or `cancelled` become eligible for archiving (i.e. they will transition into the `archive` state) after the configured `archiveCompletedAfterSeconds` time. The `failed` jobs become eligible for archiving after the configured `archiveFailedAfterSeconds` time. -Once `archive`d, jobs will be automatically deleted by pg-boss after the configured deletion period. +All jobs that are `completed`, `expired` or `cancelled` become eligible for archiving (i.e. they will transition into the `archive` state) after the configured `archiveCompletedAfterSeconds` time. Once `archive`d, jobs will be automatically deleted by pg-boss after the configured deletion period. Here's a state diagram that shows the possible states and their transitions: @@ -348,7 +347,7 @@ Queue options contain the following constructor-only settings. Specifies how long in seconds failed jobs get archived. Note: a warning will be emitted if set to lower than 60s and cron processing will be disabled. - Default: 7 days + Default: 12 hours **Monitoring options** diff --git a/src/attorney.js b/src/attorney.js index 291b9d72..43134851 100644 --- a/src/attorney.js +++ b/src/attorney.js @@ -197,12 +197,10 @@ function applyArchiveConfig (config) { } function applyArchiveFailedConfig (config) { - const ARCHIVE_DEFAULT = 60 * 60 * 24 * 7 - assert(!('archiveFailedAfterSeconds' in config) || config.archiveFailedAfterSeconds >= 1, 'configuration assert: archiveFailedAfterSeconds must be at least every second and less than ') - config.archiveFailedSeconds = config.archiveFailedAfterSeconds || ARCHIVE_DEFAULT + config.archiveFailedSeconds = config.archiveFailedAfterSeconds || config.archiveCompletedAfterSeconds config.archiveFailedInterval = `${config.archiveFailedSeconds} seconds` if (config.archiveFailedSeconds < 60) { From 19f5f0c0eacf915f8fd1cbf6345ffc061f7212a3 Mon Sep 17 00:00:00 2001 From: Kyriakos Lesgidis Date: Wed, 1 Feb 2023 23:12:46 +0200 Subject: [PATCH 4/8] Emit cron_disabled warning only once --- src/attorney.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/attorney.js b/src/attorney.js index 43134851..94f15554 100644 --- a/src/attorney.js +++ b/src/attorney.js @@ -203,7 +203,8 @@ function applyArchiveFailedConfig (config) { config.archiveFailedSeconds = config.archiveFailedAfterSeconds || config.archiveCompletedAfterSeconds config.archiveFailedInterval = `${config.archiveFailedSeconds} seconds` - if (config.archiveFailedSeconds < 60) { + // Do not emit warning twice + if (config.archiveFailedSeconds < 60 && config.archiveSeconds >= 60) { emitWarning(WARNINGS.CRON_DISABLED) } } From 0fc5b24681107deb8eb7d956644a84c7612d232f Mon Sep 17 00:00:00 2001 From: Kyriakos Lesgidis <44189854+klesgidis@users.noreply.github.com> Date: Fri, 3 Feb 2023 15:17:51 +0200 Subject: [PATCH 5/8] Update docs/readme.md Co-authored-by: Tim Jones --- docs/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/readme.md b/docs/readme.md index 46f61dec..612822ae 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -77,7 +77,7 @@ Architecturally, pg-boss is somewhat similar to queue products such as AWS SQS, All jobs start out in the `created` state and become `active` when picked up for work. If job processing completes successfully, jobs will go to `completed`. If a job fails, it will typcially enter the `failed` state. However, if a job has retry options configured, it will enter the `retry` state on failure instead and have a chance to re-enter `active` state. It's also possible for `active` jobs to become `expired`, which happens when job processing takes too long. Jobs can also enter `cancelled` state via [`cancel(id)`](#cancelid) or [`cancel([ids])`](#cancelids). -All jobs that are `completed`, `expired` or `cancelled` become eligible for archiving (i.e. they will transition into the `archive` state) after the configured `archiveCompletedAfterSeconds` time. Once `archive`d, jobs will be automatically deleted by pg-boss after the configured deletion period. +All jobs that are `completed`, `expired`, `cancelled` or `failed` become eligible for archiving (i.e. they will transition into the `archive` state) after the configured `archiveCompletedAfterSeconds` time. Once `archive`d, jobs will be automatically deleted by pg-boss after the configured deletion period. Here's a state diagram that shows the possible states and their transitions: From 993493a8c936559e9ef3a08d1951acfe9ed20b24 Mon Sep 17 00:00:00 2001 From: Kyriakos Lesgidis <44189854+klesgidis@users.noreply.github.com> Date: Fri, 3 Feb 2023 15:18:00 +0200 Subject: [PATCH 6/8] Update docs/readme.md Co-authored-by: Tim Jones --- docs/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/readme.md b/docs/readme.md index 612822ae..6a61d0b0 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -347,7 +347,7 @@ Queue options contain the following constructor-only settings. Specifies how long in seconds failed jobs get archived. Note: a warning will be emitted if set to lower than 60s and cron processing will be disabled. - Default: 12 hours + Default: `archiveCompletedAfterSeconds` **Monitoring options** From 9d496d8e77a9eb5c8c503876ff48ea2e4fb75330 Mon Sep 17 00:00:00 2001 From: Kyriakos Lesgidis Date: Mon, 6 Feb 2023 10:28:04 +0200 Subject: [PATCH 7/8] Fix undefined fallback --- src/attorney.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attorney.js b/src/attorney.js index 94f15554..0ca79c02 100644 --- a/src/attorney.js +++ b/src/attorney.js @@ -200,7 +200,7 @@ function applyArchiveFailedConfig (config) { assert(!('archiveFailedAfterSeconds' in config) || config.archiveFailedAfterSeconds >= 1, 'configuration assert: archiveFailedAfterSeconds must be at least every second and less than ') - config.archiveFailedSeconds = config.archiveFailedAfterSeconds || config.archiveCompletedAfterSeconds + config.archiveFailedSeconds = config.archiveFailedAfterSeconds || config.archiveSeconds config.archiveFailedInterval = `${config.archiveFailedSeconds} seconds` // Do not emit warning twice From f549669208450f4390ffeb6bc7938563e04648c4 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Tue, 7 Feb 2023 23:37:33 -0600 Subject: [PATCH 8/8] coverage and versioning --- package-lock.json | 116 ++++++++++++++++++++++---------------------- package.json | 2 +- test/archiveTest.js | 20 +++----- 3 files changed, 66 insertions(+), 72 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0bd1b0ad..c0ac2982 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pg-boss", - "version": "8.3.1", + "version": "8.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "pg-boss", - "version": "8.3.1", + "version": "8.4.0", "license": "MIT", "dependencies": { "cron-parser": "^4.0.0", @@ -356,9 +356,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz", - "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==", + "version": "7.20.15", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.15.tgz", + "integrity": "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -727,9 +727,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", "dev": true }, "node_modules/acorn": { @@ -1025,9 +1025,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "funding": [ { @@ -1040,10 +1040,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" @@ -1149,9 +1149,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001449", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz", - "integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==", + "version": "1.0.30001451", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz", + "integrity": "sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w==", "dev": true, "funding": [ { @@ -1475,9 +1475,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "version": "1.4.289", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.289.tgz", + "integrity": "sha512-relLdMfPBxqGCxy7Gyfm1HcbRPcFUJdlgnCPVgQ23sr1TvUrRJz0/QPoGP0+x41wOVSTN/Wi3w6YDgHiHJGOzg==", "dev": true }, "node_modules/emoji-regex": { @@ -1610,9 +1610,9 @@ } }, "node_modules/eslint": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.32.0.tgz", - "integrity": "sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz", + "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.4.1", @@ -1969,9 +1969,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.32.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.1.tgz", - "integrity": "sha512-vOjdgyd0ZHBXNsmvU+785xY8Bfe57EFbTYYk8XrROzWpr9QBvpjITvAXt9xqcE6+8cjR/g1+mfumPToxsl1www==", + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", "dev": true, "dependencies": { "array-includes": "^3.1.6", @@ -3765,9 +3765,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, "node_modules/normalize-path": { @@ -5872,9 +5872,9 @@ } }, "@babel/parser": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz", - "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==", + "version": "7.20.15", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.15.tgz", + "integrity": "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==", "dev": true }, "@babel/template": { @@ -6158,9 +6158,9 @@ "dev": true }, "@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", "dev": true }, "acorn": { @@ -6387,15 +6387,15 @@ "dev": true }, "browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" } }, "buffer-writer": { @@ -6473,9 +6473,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001449", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz", - "integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==", + "version": "1.0.30001451", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz", + "integrity": "sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w==", "dev": true }, "caseless": { @@ -6711,9 +6711,9 @@ } }, "electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "version": "1.4.289", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.289.tgz", + "integrity": "sha512-relLdMfPBxqGCxy7Gyfm1HcbRPcFUJdlgnCPVgQ23sr1TvUrRJz0/QPoGP0+x41wOVSTN/Wi3w6YDgHiHJGOzg==", "dev": true }, "emoji-regex": { @@ -6822,9 +6822,9 @@ "dev": true }, "eslint": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.32.0.tgz", - "integrity": "sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz", + "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==", "dev": true, "requires": { "@eslint/eslintrc": "^1.4.1", @@ -7142,9 +7142,9 @@ "requires": {} }, "eslint-plugin-react": { - "version": "7.32.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.1.tgz", - "integrity": "sha512-vOjdgyd0ZHBXNsmvU+785xY8Bfe57EFbTYYk8XrROzWpr9QBvpjITvAXt9xqcE6+8cjR/g1+mfumPToxsl1www==", + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", "dev": true, "requires": { "array-includes": "^3.1.6", @@ -8392,9 +8392,9 @@ } }, "node-releases": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, "normalize-path": { diff --git a/package.json b/package.json index 4d1f7bce..6e7edca0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-boss", - "version": "8.3.1", + "version": "8.4.0", "description": "Queueing jobs in Node.js using PostgreSQL like a boss", "main": "./src/index.js", "engines": { diff --git a/test/archiveTest.js b/test/archiveTest.js index 96700ea9..85ff88db 100644 --- a/test/archiveTest.js +++ b/test/archiveTest.js @@ -6,15 +6,13 @@ const { states } = require('../src/plans') describe('archive', function () { const defaults = { archiveCompletedAfterSeconds: 1, - archiveFailedAfterSeconds: 10, maintenanceIntervalSeconds: 1 } it('should archive a completed job', async function () { const config = { ...this.test.bossConfig, ...defaults } const boss = this.test.boss = await helper.start(config) - - const queue = 'archive-completed' + const queue = this.test.bossConfig.schema const jobId = await boss.send(queue) const job = await boss.fetch(queue) @@ -54,8 +52,7 @@ describe('archive', function () { it('should archive a created job', async function () { const config = { ...this.test.bossConfig, ...defaults } const boss = this.test.boss = await helper.start(config) - - const queue = 'archive-created' + const queue = this.test.bossConfig.schema const jobId = await boss.send(queue, null, { retentionSeconds: 1 }) @@ -70,8 +67,7 @@ describe('archive', function () { it('should archive a created job - cascaded config', async function () { const config = { ...this.test.bossConfig, ...defaults, retentionSeconds: 1 } const boss = this.test.boss = await helper.start(config) - - const queue = 'archive-created-cascaded-config' + const queue = this.test.bossConfig.schema const jobId = await boss.send(queue) @@ -84,10 +80,9 @@ describe('archive', function () { }) it('should not archive a failed job before the config setting', async function () { - const config = { ...this.test.bossConfig, ...defaults } + const config = { ...this.test.bossConfig, ...defaults, archiveFailedAfterSeconds: 10 } const boss = this.test.boss = await helper.start(config) - - const queue = 'archive-failed' + const queue = this.test.bossConfig.schema const failPayload = { someReason: 'nuna' } const jobId = await boss.send(queue, null, { retentionSeconds: 1 }) @@ -101,10 +96,9 @@ describe('archive', function () { }) it('should archive a failed job', async function () { - const config = { ...this.test.bossConfig, ...defaults, archiveFailedAfterSeconds: 1 } + const config = { ...this.test.bossConfig, maintenanceIntervalSeconds: 1, archiveFailedAfterSeconds: 1 } const boss = this.test.boss = await helper.start(config) - - const queue = 'archive-failed' + const queue = this.test.bossConfig.schema const failPayload = { someReason: 'nuna' } const jobId = await boss.send(queue, null, { retentionSeconds: 1 })