Merge pull request #284 from trails-cool/feat/pg-boss-v12
Upgrade pg-boss from 10 to 12
This commit is contained in:
commit
9d22ae5510
8 changed files with 117 additions and 35 deletions
|
|
@ -22,7 +22,7 @@ import { logger } from "../lib/logger.server.ts";
|
|||
* daily cap; on pass, insert one route+activity via `generateOneWalk`.
|
||||
*/
|
||||
export const demoBotGenerateJob: JobDefinition = {
|
||||
name: "demo-bot:generate",
|
||||
name: "demo-bot-generate",
|
||||
cron: "0,30 * * * *",
|
||||
retryLimit: 1,
|
||||
expireInSeconds: 120,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { logger } from "../lib/logger.server.ts";
|
|||
* `DEMO_BOT_RETENTION_DAYS` (default 14). Never touches real users.
|
||||
*/
|
||||
export const demoBotPruneJob: JobDefinition = {
|
||||
name: "demo-bot:prune",
|
||||
name: "demo-bot-prune",
|
||||
cron: "15 3 * * *",
|
||||
retryLimit: 1,
|
||||
expireInSeconds: 60,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"pg-boss": "^10.3.1"
|
||||
"pg-boss": "^12.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "catalog:"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import PgBoss from "pg-boss";
|
||||
import { PgBoss } from "pg-boss";
|
||||
|
||||
export function createBoss(connectionString: string): PgBoss {
|
||||
return new PgBoss({ connectionString });
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type PgBoss from "pg-boss";
|
||||
import type { Job } from "pg-boss";
|
||||
|
||||
export interface JobDefinition<T = unknown> {
|
||||
export interface JobDefinition<T extends object = object> {
|
||||
name: string;
|
||||
handler: (jobs: PgBoss.Job<T>[]) => Promise<unknown>;
|
||||
handler: (jobs: Job<T>[]) => Promise<unknown>;
|
||||
cron?: string;
|
||||
retryLimit?: number;
|
||||
expireInSeconds?: number;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { startWorker } from "./worker.ts";
|
||||
import { assertValidJobName, startWorker } from "./worker.ts";
|
||||
import type { JobDefinition } from "./types.ts";
|
||||
|
||||
function createMockBoss() {
|
||||
|
|
@ -87,4 +87,49 @@ describe("startWorker", () => {
|
|||
expect(boss.work).toHaveBeenCalledTimes(2);
|
||||
expect(boss.schedule).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("rejects queue names with characters that pg-boss v11+ forbids", async () => {
|
||||
const boss = createMockBoss();
|
||||
// `:` was allowed by pg-boss v10 and got us into trouble on upgrade
|
||||
// (our queues were named demo-bot:generate / demo-bot:prune until we
|
||||
// renamed them for v11+). Regression-guard that shape.
|
||||
const jobs: JobDefinition[] = [{ name: "demo-bot:generate", handler: vi.fn() }];
|
||||
|
||||
await expect(startWorker(boss as never, jobs)).rejects.toThrow(
|
||||
/Invalid pg-boss queue name/,
|
||||
);
|
||||
// start/createQueue/schedule/work must not have been called — we
|
||||
// fail before any side effects.
|
||||
expect(boss.start).not.toHaveBeenCalled();
|
||||
expect(boss.createQueue).not.toHaveBeenCalled();
|
||||
expect(boss.schedule).not.toHaveBeenCalled();
|
||||
expect(boss.work).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("assertValidJobName", () => {
|
||||
it("accepts letters, numbers, hyphens, underscores, and periods", () => {
|
||||
for (const name of [
|
||||
"demo-bot-generate",
|
||||
"expire_sessions",
|
||||
"job.v2",
|
||||
"DemoBot123",
|
||||
"a",
|
||||
]) {
|
||||
expect(() => assertValidJobName(name)).not.toThrow();
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects colon, slash, whitespace, and other punctuation", () => {
|
||||
for (const name of [
|
||||
"demo-bot:generate",
|
||||
"foo/bar",
|
||||
"foo bar",
|
||||
"foo@bar",
|
||||
"foo#bar",
|
||||
"",
|
||||
]) {
|
||||
expect(() => assertValidJobName(name)).toThrow(/Invalid pg-boss queue name/);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,31 @@
|
|||
import type PgBoss from "pg-boss";
|
||||
import type { PgBoss } from "pg-boss";
|
||||
import type { JobDefinition } from "./types.ts";
|
||||
|
||||
/**
|
||||
* Characters pg-boss v11+ accepts for queue and schedule keys. Stricter
|
||||
* than v10, which silently accepted `:` (and therefore let our
|
||||
* `demo-bot:generate` etc. names through on older pg-boss). On the
|
||||
* upgrade path we renamed them, and this guard keeps us from regressing.
|
||||
*/
|
||||
const VALID_NAME = /^[A-Za-z0-9_.-]+$/;
|
||||
|
||||
export function assertValidJobName(name: string): void {
|
||||
if (!VALID_NAME.test(name)) {
|
||||
throw new Error(
|
||||
`Invalid pg-boss queue name "${name}": only letters, numbers, hyphens, underscores, and periods are allowed.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function startWorker(
|
||||
boss: PgBoss,
|
||||
jobs: JobDefinition[],
|
||||
): Promise<void> {
|
||||
// Validate every job name before any side effects so a bad name fails
|
||||
// loudly at worker boot instead of silently producing an unreachable
|
||||
// queue somewhere downstream.
|
||||
for (const job of jobs) assertValidJobName(job.name);
|
||||
|
||||
await boss.start();
|
||||
|
||||
for (const job of jobs) {
|
||||
|
|
|
|||
68
pnpm-lock.yaml
generated
68
pnpm-lock.yaml
generated
|
|
@ -620,8 +620,8 @@ importers:
|
|||
packages/jobs:
|
||||
dependencies:
|
||||
pg-boss:
|
||||
specifier: ^10.3.1
|
||||
version: 10.4.2
|
||||
specifier: ^12.0.0
|
||||
version: 12.15.0
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: 'catalog:'
|
||||
|
|
@ -4230,9 +4230,9 @@ packages:
|
|||
crelt@1.0.6:
|
||||
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
|
||||
|
||||
cron-parser@4.9.0:
|
||||
resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
cron-parser@5.5.0:
|
||||
resolution: {integrity: sha512-oML4lKUXxizYswqmxuOCpgFS8BNUJpIu6k/2HVHyaL8Ynnf3wdf9tkns0yRdJLSIjkJ+b0DXHMZEHGpMwjnPww==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
|
|
@ -6088,6 +6088,10 @@ packages:
|
|||
resolution: {integrity: sha512-0PF8Yb1yZuQfQbq+5/pZJrtF6WQcjTd5/S4JOHs9PGFxuTqoB/icwuB44pOdURHJbRKX1PPoJZtY7R4VUoCC8w==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
non-error@0.1.0:
|
||||
resolution: {integrity: sha512-TMB1uHiGsHRGv1uYclfhivcnf0/PdFp2pNqRxXjncaAsjYMoisaQJI+SSZCqRq+VliwRTC8tsMQfmrWjDMhkPQ==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
normalize-path@3.0.0:
|
||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -6241,9 +6245,10 @@ packages:
|
|||
pathe@2.0.3:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
pg-boss@10.4.2:
|
||||
resolution: {integrity: sha512-AttEWOtSzn53av8OnCMWEanwRBvjkZCE1y5nLrZnwvkkMnlZ5XpWDpZ7sKI/BYjvi2OVieMX37arD2ACgJ750w==}
|
||||
engines: {node: '>=20'}
|
||||
pg-boss@12.15.0:
|
||||
resolution: {integrity: sha512-xw0n3M6PtAOEtPYAF/PULFqba1a27BTJOJ+tVfbd/kG++GjF5RM1xj24n5xQyek3VwDR9LObftc+ygAJ0V2kVw==}
|
||||
engines: {node: '>=22.12.0'}
|
||||
hasBin: true
|
||||
|
||||
pg-cloudflare@1.3.0:
|
||||
resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==}
|
||||
|
|
@ -6778,14 +6783,14 @@ packages:
|
|||
resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
serialize-error@13.0.1:
|
||||
resolution: {integrity: sha512-bBZaRwLH9PN5HbLCjPId4dP5bNGEtumcErgOX952IsvOhVPrm3/AeK1y0UHA/QaPG701eg0yEnOKsCOC6X/kaA==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
serialize-error@2.1.0:
|
||||
resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
serialize-error@8.1.0:
|
||||
resolution: {integrity: sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
serve-static@1.16.3:
|
||||
resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
|
@ -7018,6 +7023,10 @@ packages:
|
|||
symbol-tree@3.2.4:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
|
||||
tagged-tag@1.0.0:
|
||||
resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
tailwindcss@4.2.2:
|
||||
resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==}
|
||||
|
||||
|
|
@ -7142,10 +7151,6 @@ packages:
|
|||
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
type-fest@0.20.2:
|
||||
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
type-fest@0.21.3:
|
||||
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
|
||||
engines: {node: '>=10'}
|
||||
|
|
@ -7154,6 +7159,10 @@ packages:
|
|||
resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
type-fest@5.6.0:
|
||||
resolution: {integrity: sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
type-is@1.6.18:
|
||||
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
|
@ -11700,7 +11709,7 @@ snapshots:
|
|||
|
||||
crelt@1.0.6: {}
|
||||
|
||||
cron-parser@4.9.0:
|
||||
cron-parser@5.5.0:
|
||||
dependencies:
|
||||
luxon: 3.7.2
|
||||
|
||||
|
|
@ -14115,6 +14124,8 @@ snapshots:
|
|||
|
||||
nodemailer@8.0.5: {}
|
||||
|
||||
non-error@0.1.0: {}
|
||||
|
||||
normalize-path@3.0.0: {}
|
||||
|
||||
npm-package-arg@11.0.3:
|
||||
|
|
@ -14265,11 +14276,11 @@ snapshots:
|
|||
|
||||
pathe@2.0.3: {}
|
||||
|
||||
pg-boss@10.4.2:
|
||||
pg-boss@12.15.0:
|
||||
dependencies:
|
||||
cron-parser: 4.9.0
|
||||
cron-parser: 5.5.0
|
||||
pg: 8.20.0
|
||||
serialize-error: 8.1.0
|
||||
serialize-error: 13.0.1
|
||||
transitivePeerDependencies:
|
||||
- pg-native
|
||||
|
||||
|
|
@ -14889,11 +14900,12 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
serialize-error@2.1.0: {}
|
||||
|
||||
serialize-error@8.1.0:
|
||||
serialize-error@13.0.1:
|
||||
dependencies:
|
||||
type-fest: 0.20.2
|
||||
non-error: 0.1.0
|
||||
type-fest: 5.6.0
|
||||
|
||||
serialize-error@2.1.0: {}
|
||||
|
||||
serve-static@1.16.3:
|
||||
dependencies:
|
||||
|
|
@ -15108,6 +15120,8 @@ snapshots:
|
|||
|
||||
symbol-tree@3.2.4: {}
|
||||
|
||||
tagged-tag@1.0.0: {}
|
||||
|
||||
tailwindcss@4.2.2: {}
|
||||
|
||||
tapable@2.3.2: {}
|
||||
|
|
@ -15226,12 +15240,14 @@ snapshots:
|
|||
|
||||
type-detect@4.0.8: {}
|
||||
|
||||
type-fest@0.20.2: {}
|
||||
|
||||
type-fest@0.21.3: {}
|
||||
|
||||
type-fest@0.7.1: {}
|
||||
|
||||
type-fest@5.6.0:
|
||||
dependencies:
|
||||
tagged-tag: 1.0.0
|
||||
|
||||
type-is@1.6.18:
|
||||
dependencies:
|
||||
media-typer: 0.3.0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue