@cnstra/pg-boss 0.1.0 → 0.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 +44 -15
- package/dist/chunk-2JTKI4GS.mjs +10 -0
- package/dist/chunk-2JTKI4GS.mjs.map +1 -0
- package/dist/chunk-XJFC72LU.mjs +35 -0
- package/dist/chunk-XJFC72LU.mjs.map +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +61 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +40 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +33 -40
- package/dist/index.d.ts +33 -40
- package/dist/index.js +75 -73
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +78 -73
- package/dist/index.mjs.map +1 -1
- package/dist/postgres-progress.d.mts +75 -0
- package/dist/postgres-progress.d.ts +75 -0
- package/dist/postgres-progress.js +142 -0
- package/dist/postgres-progress.js.map +1 -0
- package/dist/postgres-progress.mjs +94 -0
- package/dist/postgres-progress.mjs.map +1 -0
- package/package.json +39 -7
package/README.md
CHANGED
|
@@ -35,13 +35,10 @@ await createCNSWorker({
|
|
|
35
35
|
cns,
|
|
36
36
|
registry,
|
|
37
37
|
queue: 'cns',
|
|
38
|
-
// Optional:
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
onHop: (h) => db.insertHop(h), // unique(stimulation_id, index) → idempotent
|
|
43
|
-
onCompleted: (s) => db.finishStimulation(s),
|
|
44
|
-
},
|
|
38
|
+
// Optional: record the name-based Stimulation → Attempt → Task history (the SAME
|
|
39
|
+
// model the DevTools use) into any ICNSStimulationRepository. In-memory just to
|
|
40
|
+
// *see* it; Postgres to keep it. One job = one stimulation; each retry = an attempt.
|
|
41
|
+
// observe: new CNSInMemoryStimulationRepository(),
|
|
45
42
|
});
|
|
46
43
|
```
|
|
47
44
|
|
|
@@ -66,18 +63,50 @@ await enqueueStimulation(boss, 'cns', job, {
|
|
|
66
63
|
|
|
67
64
|
## Retries & resume
|
|
68
65
|
|
|
69
|
-
- **
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
pg-boss reuses the **same job id** across a job's retries, so with `resume` the worker loads the
|
|
67
|
+
outstanding frontier and continues via `cns.activate(...)` — only the failed branch re-runs, with
|
|
68
|
+
its context. In pg-boss a run = stimulation = job, so the checkpoint is keyed by **job id**.
|
|
69
|
+
|
|
70
|
+
The checkpoint store is **pluggable** — three ways:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
// 1) In-package Postgres table (cns_pgboss_progress) — opt-in subpath, pulls in `pg`
|
|
74
|
+
import { CNSPgBossProgressRepository } from '@cnstra/pg-boss/postgres-progress';
|
|
75
|
+
resume: { repository: new CNSPgBossProgressRepository({ connectionString: DATABASE_URL }) }
|
|
76
|
+
|
|
77
|
+
// 2) Redis, or any other ICNSProgressRepository — the store is independent of the broker
|
|
78
|
+
import { CNSRedisProgressRepository } from '@cnstra/progress-redis';
|
|
79
|
+
resume: { repository: new CNSRedisProgressRepository({ connection }) }
|
|
80
|
+
|
|
81
|
+
// 3) No resume at all → thin mode: a retried job re-runs the WHOLE flow from the entry signal.
|
|
82
|
+
// (omit `resume`) — make neurons idempotent.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
pg-boss's `Job` has no mutable native progress field (unlike BullMQ), so a checkpoint needs a store.
|
|
86
|
+
|
|
87
|
+
**Migrations:** the Postgres table is owned by this package. Auto-created on first use, or manage it
|
|
88
|
+
yourself: `DATABASE_URL=… npx cnstra-pgboss-progress migrate` (or call `ensureSchema(pool)` from
|
|
89
|
+
`@cnstra/pg-boss/postgres-progress`).
|
|
90
|
+
|
|
91
|
+
**Row lifecycle / cleanup:** one upserted row per `job.id`. The worker **deletes it when the job
|
|
92
|
+
succeeds**. A job that fails *permanently* (retries exhausted) keeps its row — pg-boss has no
|
|
93
|
+
terminal-failure hook to key off — so prune those periodically by staleness (a still-retrying job
|
|
94
|
+
keeps `updated_at` fresh, so pick a threshold well above your longest retry window):
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
const store = new CNSPgBossProgressRepository({ connectionString: DATABASE_URL });
|
|
98
|
+
// e.g. in a daily cron: drop checkpoints untouched for over a day
|
|
99
|
+
await store.deleteStale(24 * 60 * 60 * 1000);
|
|
100
|
+
```
|
|
73
101
|
|
|
74
102
|
## What this package does / doesn't
|
|
75
103
|
|
|
76
104
|
- ✅ Job execution, retry/backoff, scheduling, singleton, concurrency → **pg-boss**.
|
|
77
|
-
- ✅
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
105
|
+
- ✅ Durable frontier **resume** across retries → a pluggable `resume.repository` (in-package
|
|
106
|
+
Postgres, `@cnstra/progress-redis`, or your own); omit it for plain re-run-from-entry.
|
|
107
|
+
- ✅ Name-based run/attempt/task **observability** → an optional `observe` store (in-memory to
|
|
108
|
+
just see it, Postgres to keep it — the same model the DevTools render).
|
|
109
|
+
- ❌ No built-in admin UI — see `@cnstra/examples` (`demo:admin`) for the CNStra retry admin.
|
|
81
110
|
|
|
82
111
|
See the full guide: https://cnstra.org/docs/integrations/pg-boss
|
|
83
112
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
__name,
|
|
8
|
+
__publicField
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=chunk-2JTKI4GS.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__name
|
|
3
|
+
} from "./chunk-2JTKI4GS.mjs";
|
|
4
|
+
|
|
5
|
+
// src/migrate.ts
|
|
6
|
+
var DEFAULT_TABLE = "cns_pgboss_progress";
|
|
7
|
+
function assertSafeTable(table) {
|
|
8
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(table)) {
|
|
9
|
+
throw new Error(`[@cnstra/pg-boss] unsafe progress table name: ${JSON.stringify(table)}`);
|
|
10
|
+
}
|
|
11
|
+
return table;
|
|
12
|
+
}
|
|
13
|
+
__name(assertSafeTable, "assertSafeTable");
|
|
14
|
+
function pgBossProgressSchemaSql(table = DEFAULT_TABLE) {
|
|
15
|
+
assertSafeTable(table);
|
|
16
|
+
return `CREATE TABLE IF NOT EXISTS ${table} (
|
|
17
|
+
key text PRIMARY KEY,
|
|
18
|
+
progress jsonb NOT NULL,
|
|
19
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20
|
+
);
|
|
21
|
+
CREATE INDEX IF NOT EXISTS ${table}_updated_idx ON ${table} (updated_at)`;
|
|
22
|
+
}
|
|
23
|
+
__name(pgBossProgressSchemaSql, "pgBossProgressSchemaSql");
|
|
24
|
+
async function ensureSchema(db, table = DEFAULT_TABLE) {
|
|
25
|
+
await db.query(pgBossProgressSchemaSql(table));
|
|
26
|
+
}
|
|
27
|
+
__name(ensureSchema, "ensureSchema");
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
DEFAULT_TABLE,
|
|
31
|
+
assertSafeTable,
|
|
32
|
+
pgBossProgressSchemaSql,
|
|
33
|
+
ensureSchema
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=chunk-XJFC72LU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/migrate.ts"],"sourcesContent":["/**\n * Schema / migrations for the pg-boss progress table (`cns_pgboss_progress`).\n *\n * The package OWNS this schema so you can manage it explicitly (a migration step in\n * your own tooling) instead of relying on the repository's lazy auto-create. Run it\n * via the `cnstra-pgboss-progress migrate` CLI, or call `ensureSchema(db)` yourself\n * with any pg client/pool.\n */\n\n/** Minimal pg client surface (a `pg` Pool or Client satisfies it). */\nexport interface IPgQueryable {\n query(text: string, params?: unknown[]): Promise<{ rows: unknown[] }>;\n}\n\nexport const DEFAULT_TABLE = 'cns_pgboss_progress';\n\n/** Guard the table identifier (it is interpolated into DDL/DML, not parameterised). */\nexport function assertSafeTable(table: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(table)) {\n throw new Error(\n `[@cnstra/pg-boss] unsafe progress table name: ${JSON.stringify(table)}`\n );\n }\n return table;\n}\n\n/** The CREATE TABLE for the progress store. One upserted row per key (job id). */\nexport function pgBossProgressSchemaSql(table: string = DEFAULT_TABLE): string {\n assertSafeTable(table);\n // `updated_at` + its index back `deleteStale()`: a row is deleted when its job\n // succeeds, but a job that fails PERMANENTLY (retries exhausted) leaves its row —\n // pg-boss has no terminal-failure hook to key off. Pruning by staleness collects\n // those, and the index keeps the sweep cheap.\n return `CREATE TABLE IF NOT EXISTS ${table} (\n key text PRIMARY KEY,\n progress jsonb NOT NULL,\n updated_at timestamptz NOT NULL DEFAULT now()\n);\nCREATE INDEX IF NOT EXISTS ${table}_updated_idx ON ${table} (updated_at)`;\n}\n\n/** Idempotently create the progress table. Safe to run repeatedly. */\nexport async function ensureSchema(\n db: IPgQueryable,\n table: string = DEFAULT_TABLE\n): Promise<void> {\n await db.query(pgBossProgressSchemaSql(table));\n}\n"],"mappings":";;;;;AAcO,IAAMA,gBAAgB;AAGtB,SAASC,gBAAgBC,OAAa;AACzC,MAAI,CAAC,2BAA2BC,KAAKD,KAAAA,GAAQ;AACzC,UAAM,IAAIE,MACN,iDAAiDC,KAAKC,UAAUJ,KAAAA,CAAAA,EAAQ;EAEhF;AACA,SAAOA;AACX;AAPgBD;AAUT,SAASM,wBAAwBL,QAAgBF,eAAa;AACjEC,kBAAgBC,KAAAA;AAKhB,SAAO,8BAA8BA,KAAAA;;;;;6BAKZA,KAAAA,mBAAwBA,KAAAA;AACrD;AAZgBK;AAehB,eAAsBC,aAClBC,IACAP,QAAgBF,eAAa;AAE7B,QAAMS,GAAGC,MAAMH,wBAAwBL,KAAAA,CAAAA;AAC3C;AALsBM;","names":["DEFAULT_TABLE","assertSafeTable","table","test","Error","JSON","stringify","pgBossProgressSchemaSql","ensureSchema","db","query"]}
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
|
+
|
|
5
|
+
// src/cli.ts
|
|
6
|
+
var import_pg = require("pg");
|
|
7
|
+
|
|
8
|
+
// src/migrate.ts
|
|
9
|
+
var DEFAULT_TABLE = "cns_pgboss_progress";
|
|
10
|
+
function assertSafeTable(table) {
|
|
11
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(table)) {
|
|
12
|
+
throw new Error(`[@cnstra/pg-boss] unsafe progress table name: ${JSON.stringify(table)}`);
|
|
13
|
+
}
|
|
14
|
+
return table;
|
|
15
|
+
}
|
|
16
|
+
__name(assertSafeTable, "assertSafeTable");
|
|
17
|
+
function pgBossProgressSchemaSql(table = DEFAULT_TABLE) {
|
|
18
|
+
assertSafeTable(table);
|
|
19
|
+
return `CREATE TABLE IF NOT EXISTS ${table} (
|
|
20
|
+
key text PRIMARY KEY,
|
|
21
|
+
progress jsonb NOT NULL,
|
|
22
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
23
|
+
);
|
|
24
|
+
CREATE INDEX IF NOT EXISTS ${table}_updated_idx ON ${table} (updated_at)`;
|
|
25
|
+
}
|
|
26
|
+
__name(pgBossProgressSchemaSql, "pgBossProgressSchemaSql");
|
|
27
|
+
async function ensureSchema(db, table = DEFAULT_TABLE) {
|
|
28
|
+
await db.query(pgBossProgressSchemaSql(table));
|
|
29
|
+
}
|
|
30
|
+
__name(ensureSchema, "ensureSchema");
|
|
31
|
+
|
|
32
|
+
// src/cli.ts
|
|
33
|
+
async function main() {
|
|
34
|
+
var _a;
|
|
35
|
+
const cmd = process.argv[2];
|
|
36
|
+
if (cmd !== "migrate") {
|
|
37
|
+
console.error("usage: cnstra-pgboss-progress migrate");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
const url = process.env.DATABASE_URL;
|
|
41
|
+
if (!url) {
|
|
42
|
+
console.error("DATABASE_URL is required");
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
const table = (_a = process.env.CNS_PGBOSS_PROGRESS_TABLE) != null ? _a : DEFAULT_TABLE;
|
|
46
|
+
const pool = new import_pg.Pool({
|
|
47
|
+
connectionString: url
|
|
48
|
+
});
|
|
49
|
+
try {
|
|
50
|
+
await ensureSchema(pool, table);
|
|
51
|
+
console.log(`\u2713 ensured progress table "${table}"`);
|
|
52
|
+
} finally {
|
|
53
|
+
await pool.end();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
__name(main, "main");
|
|
57
|
+
void main().catch((e) => {
|
|
58
|
+
console.error(e);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/migrate.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `cnstra-pgboss-progress migrate` — create the pg-boss progress table.\n *\n * DATABASE_URL=postgres://... cnstra-pgboss-progress migrate\n * CNS_PGBOSS_PROGRESS_TABLE=my_table (optional; default cns_pgboss_progress)\n */\nimport { Pool } from 'pg';\nimport { ensureSchema, DEFAULT_TABLE } from './migrate';\n\nasync function main(): Promise<void> {\n const cmd = process.argv[2];\n if (cmd !== 'migrate') {\n console.error('usage: cnstra-pgboss-progress migrate'); // eslint-disable-line no-console\n process.exit(1);\n }\n const url = process.env.DATABASE_URL;\n if (!url) {\n console.error('DATABASE_URL is required'); // eslint-disable-line no-console\n process.exit(1);\n }\n const table = process.env.CNS_PGBOSS_PROGRESS_TABLE ?? DEFAULT_TABLE;\n const pool = new Pool({ connectionString: url });\n try {\n await ensureSchema(pool, table);\n // eslint-disable-next-line no-console\n console.log(`✓ ensured progress table \"${table}\"`);\n } finally {\n await pool.end();\n }\n}\n\nvoid main().catch(e => {\n console.error(e); // eslint-disable-line no-console\n process.exit(1);\n});\n","/**\n * Schema / migrations for the pg-boss progress table (`cns_pgboss_progress`).\n *\n * The package OWNS this schema so you can manage it explicitly (a migration step in\n * your own tooling) instead of relying on the repository's lazy auto-create. Run it\n * via the `cnstra-pgboss-progress migrate` CLI, or call `ensureSchema(db)` yourself\n * with any pg client/pool.\n */\n\n/** Minimal pg client surface (a `pg` Pool or Client satisfies it). */\nexport interface IPgQueryable {\n query(text: string, params?: unknown[]): Promise<{ rows: unknown[] }>;\n}\n\nexport const DEFAULT_TABLE = 'cns_pgboss_progress';\n\n/** Guard the table identifier (it is interpolated into DDL/DML, not parameterised). */\nexport function assertSafeTable(table: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(table)) {\n throw new Error(\n `[@cnstra/pg-boss] unsafe progress table name: ${JSON.stringify(table)}`\n );\n }\n return table;\n}\n\n/** The CREATE TABLE for the progress store. One upserted row per key (job id). */\nexport function pgBossProgressSchemaSql(table: string = DEFAULT_TABLE): string {\n assertSafeTable(table);\n // `updated_at` + its index back `deleteStale()`: a row is deleted when its job\n // succeeds, but a job that fails PERMANENTLY (retries exhausted) leaves its row —\n // pg-boss has no terminal-failure hook to key off. Pruning by staleness collects\n // those, and the index keeps the sweep cheap.\n return `CREATE TABLE IF NOT EXISTS ${table} (\n key text PRIMARY KEY,\n progress jsonb NOT NULL,\n updated_at timestamptz NOT NULL DEFAULT now()\n);\nCREATE INDEX IF NOT EXISTS ${table}_updated_idx ON ${table} (updated_at)`;\n}\n\n/** Idempotently create the progress table. Safe to run repeatedly. */\nexport async function ensureSchema(\n db: IPgQueryable,\n table: string = DEFAULT_TABLE\n): Promise<void> {\n await db.query(pgBossProgressSchemaSql(table));\n}\n"],"mappings":";;;;;AAOA,gBAAqB;;;ACOd,IAAMA,gBAAgB;AAGtB,SAASC,gBAAgBC,OAAa;AACzC,MAAI,CAAC,2BAA2BC,KAAKD,KAAAA,GAAQ;AACzC,UAAM,IAAIE,MACN,iDAAiDC,KAAKC,UAAUJ,KAAAA,CAAAA,EAAQ;EAEhF;AACA,SAAOA;AACX;AAPgBD;AAUT,SAASM,wBAAwBL,QAAgBF,eAAa;AACjEC,kBAAgBC,KAAAA;AAKhB,SAAO,8BAA8BA,KAAAA;;;;;6BAKZA,KAAAA,mBAAwBA,KAAAA;AACrD;AAZgBK;AAehB,eAAsBC,aAClBC,IACAP,QAAgBF,eAAa;AAE7B,QAAMS,GAAGC,MAAMH,wBAAwBL,KAAAA,CAAAA;AAC3C;AALsBM;;;ADhCtB,eAAeG,OAAAA;;AACX,QAAMC,MAAMC,QAAQC,KAAK,CAAA;AACzB,MAAIF,QAAQ,WAAW;AACnBG,YAAQC,MAAM,uCAAA;AACdH,YAAQI,KAAK,CAAA;EACjB;AACA,QAAMC,MAAML,QAAQM,IAAIC;AACxB,MAAI,CAACF,KAAK;AACNH,YAAQC,MAAM,0BAAA;AACdH,YAAQI,KAAK,CAAA;EACjB;AACA,QAAMI,SAAQR,aAAQM,IAAIG,8BAAZT,YAAyCU;AACvD,QAAMC,OAAO,IAAIC,eAAK;IAAEC,kBAAkBR;EAAI,CAAA;AAC9C,MAAI;AACA,UAAMS,aAAaH,MAAMH,KAAAA;AAEzBN,YAAQa,IAAI,kCAA6BP,KAAAA,GAAQ;EACrD,UAAA;AACI,UAAMG,KAAKK,IAAG;EAClB;AACJ;AApBelB;AAsBf,KAAKA,KAAAA,EAAOmB,MAAMC,CAAAA,MAAAA;AACdhB,UAAQC,MAAMe,CAAAA;AACdlB,UAAQI,KAAK,CAAA;AACjB,CAAA;","names":["DEFAULT_TABLE","assertSafeTable","table","test","Error","JSON","stringify","pgBossProgressSchemaSql","ensureSchema","db","query","main","cmd","process","argv","console","error","exit","url","env","DATABASE_URL","table","CNS_PGBOSS_PROGRESS_TABLE","DEFAULT_TABLE","pool","Pool","connectionString","ensureSchema","log","end","catch","e"]}
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_TABLE,
|
|
4
|
+
ensureSchema
|
|
5
|
+
} from "./chunk-XJFC72LU.mjs";
|
|
6
|
+
import {
|
|
7
|
+
__name
|
|
8
|
+
} from "./chunk-2JTKI4GS.mjs";
|
|
9
|
+
|
|
10
|
+
// src/cli.ts
|
|
11
|
+
import { Pool } from "pg";
|
|
12
|
+
async function main() {
|
|
13
|
+
var _a;
|
|
14
|
+
const cmd = process.argv[2];
|
|
15
|
+
if (cmd !== "migrate") {
|
|
16
|
+
console.error("usage: cnstra-pgboss-progress migrate");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const url = process.env.DATABASE_URL;
|
|
20
|
+
if (!url) {
|
|
21
|
+
console.error("DATABASE_URL is required");
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const table = (_a = process.env.CNS_PGBOSS_PROGRESS_TABLE) != null ? _a : DEFAULT_TABLE;
|
|
25
|
+
const pool = new Pool({
|
|
26
|
+
connectionString: url
|
|
27
|
+
});
|
|
28
|
+
try {
|
|
29
|
+
await ensureSchema(pool, table);
|
|
30
|
+
console.log(`\u2713 ensured progress table "${table}"`);
|
|
31
|
+
} finally {
|
|
32
|
+
await pool.end();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
__name(main, "main");
|
|
36
|
+
void main().catch((e) => {
|
|
37
|
+
console.error(e);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=cli.mjs.map
|
package/dist/cli.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `cnstra-pgboss-progress migrate` — create the pg-boss progress table.\n *\n * DATABASE_URL=postgres://... cnstra-pgboss-progress migrate\n * CNS_PGBOSS_PROGRESS_TABLE=my_table (optional; default cns_pgboss_progress)\n */\nimport { Pool } from 'pg';\nimport { ensureSchema, DEFAULT_TABLE } from './migrate';\n\nasync function main(): Promise<void> {\n const cmd = process.argv[2];\n if (cmd !== 'migrate') {\n console.error('usage: cnstra-pgboss-progress migrate'); // eslint-disable-line no-console\n process.exit(1);\n }\n const url = process.env.DATABASE_URL;\n if (!url) {\n console.error('DATABASE_URL is required'); // eslint-disable-line no-console\n process.exit(1);\n }\n const table = process.env.CNS_PGBOSS_PROGRESS_TABLE ?? DEFAULT_TABLE;\n const pool = new Pool({ connectionString: url });\n try {\n await ensureSchema(pool, table);\n // eslint-disable-next-line no-console\n console.log(`✓ ensured progress table \"${table}\"`);\n } finally {\n await pool.end();\n }\n}\n\nvoid main().catch(e => {\n console.error(e); // eslint-disable-line no-console\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;AAOA,SAASA,YAAY;AAGrB,eAAeC,OAAAA;;AACX,QAAMC,MAAMC,QAAQC,KAAK,CAAA;AACzB,MAAIF,QAAQ,WAAW;AACnBG,YAAQC,MAAM,uCAAA;AACdH,YAAQI,KAAK,CAAA;EACjB;AACA,QAAMC,MAAML,QAAQM,IAAIC;AACxB,MAAI,CAACF,KAAK;AACNH,YAAQC,MAAM,0BAAA;AACdH,YAAQI,KAAK,CAAA;EACjB;AACA,QAAMI,SAAQR,aAAQM,IAAIG,8BAAZT,YAAyCU;AACvD,QAAMC,OAAO,IAAIC,KAAK;IAAEC,kBAAkBR;EAAI,CAAA;AAC9C,MAAI;AACA,UAAMS,aAAaH,MAAMH,KAAAA;AAEzBN,YAAQa,IAAI,kCAA6BP,KAAAA,GAAQ;EACrD,UAAA;AACI,UAAMG,KAAKK,IAAG;EAClB;AACJ;AApBelB;AAsBf,KAAKA,KAAAA,EAAOmB,MAAMC,CAAAA,MAAAA;AACdhB,UAAQC,MAAMe,CAAAA;AACdlB,UAAQI,KAAK,CAAA;AACjB,CAAA;","names":["Pool","main","cmd","process","argv","console","error","exit","url","env","DATABASE_URL","table","CNS_PGBOSS_PROGRESS_TABLE","DEFAULT_TABLE","pool","Pool","connectionString","ensureSchema","log","end","catch","e"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CNSPersistOptionsRegistry, ICNSStimulationRepository, ICNSProgressRepository, ICNSProgressRecordingStrategy } from '@cnstra/persist';
|
|
2
|
+
import { ICNS } from '@cnstra/types';
|
|
3
|
+
import { CNSCollateral } from '@cnstra/core';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Minimal, structural view of the pg-boss surface this package touches.
|
|
@@ -12,6 +14,8 @@ interface IPgBossJob<TData = unknown> {
|
|
|
12
14
|
id: string;
|
|
13
15
|
name: string;
|
|
14
16
|
data: TData;
|
|
17
|
+
/** 0-based retry count (pg-boss `Job.retryCount`); drives the attempt number. */
|
|
18
|
+
retryCount?: number;
|
|
15
19
|
}
|
|
16
20
|
interface IPgBossLike {
|
|
17
21
|
send(name: string, data: object, options?: Record<string, unknown>): Promise<string | null>;
|
|
@@ -29,42 +33,6 @@ interface TCNSStimulationJobData {
|
|
|
29
33
|
/** Optional per-run cap on neuron hops. */
|
|
30
34
|
maxNeuronHops?: number;
|
|
31
35
|
}
|
|
32
|
-
/** One per-hop progress record (mirrors the devtools `CNSDTOHop` shape). */
|
|
33
|
-
interface TCNSHopRecord {
|
|
34
|
-
jobId: string;
|
|
35
|
-
index: number;
|
|
36
|
-
neuronName: string | null;
|
|
37
|
-
inputCollateral: string | null;
|
|
38
|
-
outputCollateral: string | null;
|
|
39
|
-
inputPayload: unknown;
|
|
40
|
-
outputPayload: unknown;
|
|
41
|
-
error: string | null;
|
|
42
|
-
at: number;
|
|
43
|
-
}
|
|
44
|
-
/** Lifecycle record for one stimulation (one job). */
|
|
45
|
-
interface TCNSStimulationLifecycle {
|
|
46
|
-
jobId: string;
|
|
47
|
-
collateralName: string;
|
|
48
|
-
payload: unknown;
|
|
49
|
-
status: 'running' | 'completed' | 'failed';
|
|
50
|
-
startedAt: number;
|
|
51
|
-
completedAt?: number;
|
|
52
|
-
hopCount: number;
|
|
53
|
-
error?: string;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Where progress is written (Postgres, OIMDB, logs, …).
|
|
57
|
-
*
|
|
58
|
-
* If `onHop` returns a Promise, CNStra waits for it **before enqueuing the next
|
|
59
|
-
* hop** — i.e. each step is durably committed before the flow advances. This is
|
|
60
|
-
* the per-hop checkpoint barrier that makes an admin/progress view truthful
|
|
61
|
-
* across restarts.
|
|
62
|
-
*/
|
|
63
|
-
interface ICNSProgressSink {
|
|
64
|
-
onStarted?(rec: TCNSStimulationLifecycle): void | Promise<void>;
|
|
65
|
-
onHop?(rec: TCNSHopRecord): void | Promise<void>;
|
|
66
|
-
onCompleted?(rec: TCNSStimulationLifecycle): void | Promise<void>;
|
|
67
|
-
}
|
|
68
36
|
/** Structural view of the response passed to `onResponse` (not exported by core). */
|
|
69
37
|
interface ICNSResponseLike {
|
|
70
38
|
inputSignal?: {
|
|
@@ -87,8 +55,33 @@ interface TCNSWorkerOptions {
|
|
|
87
55
|
registry: CNSPersistOptionsRegistry;
|
|
88
56
|
/** Queue name to consume. */
|
|
89
57
|
queue: string;
|
|
90
|
-
/**
|
|
91
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Optional **observability** store: the canonical name-based
|
|
60
|
+
* Stimulation → Attempt → Task history (the SAME model the devtools use),
|
|
61
|
+
* written per hop via a {@link CNSStimulationPersistor}. Pass a
|
|
62
|
+
* `CNSInMemoryStimulationRepository` to just *see* progress (ephemeral), or a
|
|
63
|
+
* Postgres store to keep it. It records history; it does not drive resume —
|
|
64
|
+
* that is `resume` below. One job = one stimulation (`stimulationId` = job id),
|
|
65
|
+
* each pg-boss retry = a new attempt.
|
|
66
|
+
*/
|
|
67
|
+
observe?: ICNSStimulationRepository;
|
|
68
|
+
/**
|
|
69
|
+
* Optional durable **resume**. When set, the worker records the run's
|
|
70
|
+
* outstanding frontier (by name) into `repository` as it advances, and a
|
|
71
|
+
* retried job (same job id) resumes from that frontier via `cns.activate(...)`
|
|
72
|
+
* instead of re-running from the entry signal. The record's lifecycle matches
|
|
73
|
+
* the pg-boss job row: dropped on success, kept on failure for the retry.
|
|
74
|
+
*
|
|
75
|
+
* Requires every neuron/collateral that can appear in the frontier to be in
|
|
76
|
+
* the `registry` (not just the entry collaterals). Neurons should still be
|
|
77
|
+
* idempotent — resume narrows re-execution to the unfinished branch, it does
|
|
78
|
+
* not make individual hops exactly-once.
|
|
79
|
+
*/
|
|
80
|
+
resume?: {
|
|
81
|
+
repository: ICNSProgressRepository;
|
|
82
|
+
/** When to persist during the run. Defaults to debounce + max-staleness. */
|
|
83
|
+
strategy?: ICNSProgressRecordingStrategy;
|
|
84
|
+
};
|
|
92
85
|
/** pg-boss `work` options (batchSize, pollingIntervalSeconds, …). */
|
|
93
86
|
workOptions?: Record<string, unknown>;
|
|
94
87
|
}
|
|
@@ -123,4 +116,4 @@ declare function stimulationJob(registry: CNSPersistOptionsRegistry, collateral:
|
|
|
123
116
|
/** Send a stimulation job to a pg-boss queue. Returns the job id. */
|
|
124
117
|
declare function enqueueStimulation(boss: IPgBossLike, queue: string, job: TCNSStimulationJobData, options?: TCNSSendOptions): Promise<string | null>;
|
|
125
118
|
|
|
126
|
-
export { type
|
|
119
|
+
export { type ICNSResponseLike, type IPgBossJob, type IPgBossLike, type TCNSSendOptions, type TCNSStimulationJobData, type TCNSWorkerOptions, createCNSWorker, enqueueStimulation, stimulationJob };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CNSPersistOptionsRegistry, ICNSStimulationRepository, ICNSProgressRepository, ICNSProgressRecordingStrategy } from '@cnstra/persist';
|
|
2
|
+
import { ICNS } from '@cnstra/types';
|
|
3
|
+
import { CNSCollateral } from '@cnstra/core';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Minimal, structural view of the pg-boss surface this package touches.
|
|
@@ -12,6 +14,8 @@ interface IPgBossJob<TData = unknown> {
|
|
|
12
14
|
id: string;
|
|
13
15
|
name: string;
|
|
14
16
|
data: TData;
|
|
17
|
+
/** 0-based retry count (pg-boss `Job.retryCount`); drives the attempt number. */
|
|
18
|
+
retryCount?: number;
|
|
15
19
|
}
|
|
16
20
|
interface IPgBossLike {
|
|
17
21
|
send(name: string, data: object, options?: Record<string, unknown>): Promise<string | null>;
|
|
@@ -29,42 +33,6 @@ interface TCNSStimulationJobData {
|
|
|
29
33
|
/** Optional per-run cap on neuron hops. */
|
|
30
34
|
maxNeuronHops?: number;
|
|
31
35
|
}
|
|
32
|
-
/** One per-hop progress record (mirrors the devtools `CNSDTOHop` shape). */
|
|
33
|
-
interface TCNSHopRecord {
|
|
34
|
-
jobId: string;
|
|
35
|
-
index: number;
|
|
36
|
-
neuronName: string | null;
|
|
37
|
-
inputCollateral: string | null;
|
|
38
|
-
outputCollateral: string | null;
|
|
39
|
-
inputPayload: unknown;
|
|
40
|
-
outputPayload: unknown;
|
|
41
|
-
error: string | null;
|
|
42
|
-
at: number;
|
|
43
|
-
}
|
|
44
|
-
/** Lifecycle record for one stimulation (one job). */
|
|
45
|
-
interface TCNSStimulationLifecycle {
|
|
46
|
-
jobId: string;
|
|
47
|
-
collateralName: string;
|
|
48
|
-
payload: unknown;
|
|
49
|
-
status: 'running' | 'completed' | 'failed';
|
|
50
|
-
startedAt: number;
|
|
51
|
-
completedAt?: number;
|
|
52
|
-
hopCount: number;
|
|
53
|
-
error?: string;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Where progress is written (Postgres, OIMDB, logs, …).
|
|
57
|
-
*
|
|
58
|
-
* If `onHop` returns a Promise, CNStra waits for it **before enqueuing the next
|
|
59
|
-
* hop** — i.e. each step is durably committed before the flow advances. This is
|
|
60
|
-
* the per-hop checkpoint barrier that makes an admin/progress view truthful
|
|
61
|
-
* across restarts.
|
|
62
|
-
*/
|
|
63
|
-
interface ICNSProgressSink {
|
|
64
|
-
onStarted?(rec: TCNSStimulationLifecycle): void | Promise<void>;
|
|
65
|
-
onHop?(rec: TCNSHopRecord): void | Promise<void>;
|
|
66
|
-
onCompleted?(rec: TCNSStimulationLifecycle): void | Promise<void>;
|
|
67
|
-
}
|
|
68
36
|
/** Structural view of the response passed to `onResponse` (not exported by core). */
|
|
69
37
|
interface ICNSResponseLike {
|
|
70
38
|
inputSignal?: {
|
|
@@ -87,8 +55,33 @@ interface TCNSWorkerOptions {
|
|
|
87
55
|
registry: CNSPersistOptionsRegistry;
|
|
88
56
|
/** Queue name to consume. */
|
|
89
57
|
queue: string;
|
|
90
|
-
/**
|
|
91
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Optional **observability** store: the canonical name-based
|
|
60
|
+
* Stimulation → Attempt → Task history (the SAME model the devtools use),
|
|
61
|
+
* written per hop via a {@link CNSStimulationPersistor}. Pass a
|
|
62
|
+
* `CNSInMemoryStimulationRepository` to just *see* progress (ephemeral), or a
|
|
63
|
+
* Postgres store to keep it. It records history; it does not drive resume —
|
|
64
|
+
* that is `resume` below. One job = one stimulation (`stimulationId` = job id),
|
|
65
|
+
* each pg-boss retry = a new attempt.
|
|
66
|
+
*/
|
|
67
|
+
observe?: ICNSStimulationRepository;
|
|
68
|
+
/**
|
|
69
|
+
* Optional durable **resume**. When set, the worker records the run's
|
|
70
|
+
* outstanding frontier (by name) into `repository` as it advances, and a
|
|
71
|
+
* retried job (same job id) resumes from that frontier via `cns.activate(...)`
|
|
72
|
+
* instead of re-running from the entry signal. The record's lifecycle matches
|
|
73
|
+
* the pg-boss job row: dropped on success, kept on failure for the retry.
|
|
74
|
+
*
|
|
75
|
+
* Requires every neuron/collateral that can appear in the frontier to be in
|
|
76
|
+
* the `registry` (not just the entry collaterals). Neurons should still be
|
|
77
|
+
* idempotent — resume narrows re-execution to the unfinished branch, it does
|
|
78
|
+
* not make individual hops exactly-once.
|
|
79
|
+
*/
|
|
80
|
+
resume?: {
|
|
81
|
+
repository: ICNSProgressRepository;
|
|
82
|
+
/** When to persist during the run. Defaults to debounce + max-staleness. */
|
|
83
|
+
strategy?: ICNSProgressRecordingStrategy;
|
|
84
|
+
};
|
|
92
85
|
/** pg-boss `work` options (batchSize, pollingIntervalSeconds, …). */
|
|
93
86
|
workOptions?: Record<string, unknown>;
|
|
94
87
|
}
|
|
@@ -123,4 +116,4 @@ declare function stimulationJob(registry: CNSPersistOptionsRegistry, collateral:
|
|
|
123
116
|
/** Send a stimulation job to a pg-boss queue. Returns the job id. */
|
|
124
117
|
declare function enqueueStimulation(boss: IPgBossLike, queue: string, job: TCNSStimulationJobData, options?: TCNSSendOptions): Promise<string | null>;
|
|
125
118
|
|
|
126
|
-
export { type
|
|
119
|
+
export { type ICNSResponseLike, type IPgBossJob, type IPgBossLike, type TCNSSendOptions, type TCNSStimulationJobData, type TCNSWorkerOptions, createCNSWorker, enqueueStimulation, stimulationJob };
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
6
|
var __export = (target, all) => {
|
|
6
7
|
for (var name in all)
|
|
7
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -26,105 +27,106 @@ __export(index_exports, {
|
|
|
26
27
|
module.exports = __toCommonJS(index_exports);
|
|
27
28
|
|
|
28
29
|
// src/worker.ts
|
|
29
|
-
|
|
30
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
31
|
-
const outputCol = (_a = resp.outputSignal) == null ? void 0 : _a.collateral;
|
|
32
|
-
const inputCol = (_b = resp.inputSignal) == null ? void 0 : _b.collateral;
|
|
33
|
-
const ownerNeuron = outputCol ? cns.network.getParentNeuronByCollateral(outputCol) : null;
|
|
34
|
-
return {
|
|
35
|
-
jobId,
|
|
36
|
-
index,
|
|
37
|
-
neuronName: ownerNeuron ? (_c = registry.getNeuronName(ownerNeuron)) != null ? _c : null : null,
|
|
38
|
-
inputCollateral: inputCol ? (_d = registry.getCollateralName(inputCol)) != null ? _d : null : null,
|
|
39
|
-
outputCollateral: outputCol ? (_e = registry.getCollateralName(outputCol)) != null ? _e : null : null,
|
|
40
|
-
inputPayload: (_i = (_h = (_f = resp.inputSignal) == null ? void 0 : _f.payload) != null ? _h : (_g = resp.outputSignal) == null ? void 0 : _g.payload) != null ? _i : null,
|
|
41
|
-
outputPayload: outputCol ? (_k = (_j = resp.outputSignal) == null ? void 0 : _j.payload) != null ? _k : null : null,
|
|
42
|
-
error: resp.error != null ? String(resp.error) : null,
|
|
43
|
-
at: Date.now()
|
|
44
|
-
};
|
|
45
|
-
}
|
|
30
|
+
var import_persist = require("@cnstra/persist");
|
|
46
31
|
function createCNSWorker(options) {
|
|
47
|
-
const { boss, cns, registry, queue,
|
|
48
|
-
const
|
|
49
|
-
|
|
32
|
+
const { boss, cns, registry, queue, observe, resume, workOptions } = options;
|
|
33
|
+
const serializer = resume ? new import_persist.CNSProgressSerializer(registry) : void 0;
|
|
34
|
+
const runJob = /* @__PURE__ */ __name(async (job) => {
|
|
35
|
+
var _a;
|
|
50
36
|
const { collateralName, payload, maxNeuronHops } = job.data;
|
|
51
37
|
const collateral = registry.getCollateral(collateralName);
|
|
52
38
|
if (!collateral) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
`[@cnstra/pg-boss] Unknown collateral "${collateralName}". Register it in the CNSPersistOptionsRegistry.`
|
|
55
|
-
);
|
|
39
|
+
throw new Error(`[@cnstra/pg-boss] Unknown collateral "${collateralName}". Register it in the CNSPersistOptionsRegistry.`);
|
|
56
40
|
}
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
41
|
+
const recorder = resume && serializer ? new import_persist.CNSProgressRecorder({
|
|
42
|
+
serializer,
|
|
43
|
+
repository: resume.repository,
|
|
44
|
+
key: job.id,
|
|
45
|
+
strategy: resume.strategy
|
|
46
|
+
}) : void 0;
|
|
47
|
+
const attemptNumber = ((_a = job.retryCount) != null ? _a : 0) + 1;
|
|
48
|
+
const persistor = observe ? new import_persist.CNSStimulationPersistor({
|
|
49
|
+
repository: observe,
|
|
50
|
+
registry,
|
|
51
|
+
stimulationId: job.id,
|
|
52
|
+
stimulationAttemptId: `${job.id}#${attemptNumber}`,
|
|
53
|
+
attemptNumber,
|
|
54
|
+
entry: [
|
|
55
|
+
{
|
|
56
|
+
collateralName,
|
|
57
|
+
payload
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
volume: "full"
|
|
61
|
+
}) : void 0;
|
|
62
|
+
const onResponse = /* @__PURE__ */ __name((resp) => {
|
|
63
|
+
const r = resp;
|
|
64
|
+
recorder == null ? void 0 : recorder.onResponse(r);
|
|
65
|
+
persistor == null ? void 0 : persistor.onResponse(r);
|
|
66
|
+
}, "onResponse");
|
|
67
|
+
const stimulationContext = {
|
|
68
|
+
stimulationId: job.id,
|
|
69
|
+
attemptNumber
|
|
70
|
+
};
|
|
71
|
+
let stimulation;
|
|
72
|
+
if (resume && serializer) {
|
|
73
|
+
const saved = await resume.repository.load(job.id);
|
|
74
|
+
if (saved) {
|
|
75
|
+
const { tasks, ctx } = serializer.hydrate(saved);
|
|
76
|
+
stimulation = cns.activate(tasks, {
|
|
77
|
+
maxNeuronHops,
|
|
78
|
+
ctx,
|
|
79
|
+
onResponse,
|
|
80
|
+
stimulationContext
|
|
81
|
+
});
|
|
80
82
|
}
|
|
81
|
-
}
|
|
83
|
+
}
|
|
84
|
+
if (!stimulation) {
|
|
85
|
+
stimulation = cns.stimulate(collateral.createSignal(payload), {
|
|
86
|
+
maxNeuronHops,
|
|
87
|
+
onResponse,
|
|
88
|
+
stimulationContext
|
|
89
|
+
});
|
|
90
|
+
}
|
|
82
91
|
try {
|
|
83
92
|
await stimulation.waitUntilComplete();
|
|
84
|
-
|
|
85
|
-
jobId: job.id,
|
|
86
|
-
collateralName,
|
|
87
|
-
payload,
|
|
88
|
-
status: "completed",
|
|
89
|
-
startedAt,
|
|
90
|
-
completedAt: Date.now(),
|
|
91
|
-
hopCount
|
|
92
|
-
}));
|
|
93
|
+
if (resume) await resume.repository.delete(job.id);
|
|
93
94
|
} catch (err) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
payload,
|
|
98
|
-
status: "failed",
|
|
99
|
-
startedAt,
|
|
100
|
-
completedAt: Date.now(),
|
|
101
|
-
hopCount,
|
|
102
|
-
error: err instanceof Error ? err.message : String(err)
|
|
103
|
-
}));
|
|
95
|
+
if (resume && serializer) {
|
|
96
|
+
await resume.repository.save(job.id, serializer.serialize(stimulation));
|
|
97
|
+
}
|
|
104
98
|
throw err;
|
|
99
|
+
} finally {
|
|
100
|
+
recorder == null ? void 0 : recorder.dispose();
|
|
101
|
+
persistor == null ? void 0 : persistor.dispose();
|
|
105
102
|
}
|
|
106
|
-
};
|
|
107
|
-
const handler = async (jobs) => {
|
|
103
|
+
}, "runJob");
|
|
104
|
+
const handler = /* @__PURE__ */ __name(async (jobs) => {
|
|
108
105
|
for (const job of jobs) {
|
|
109
106
|
await runJob(job);
|
|
110
107
|
}
|
|
111
|
-
};
|
|
108
|
+
}, "handler");
|
|
112
109
|
return workOptions ? boss.work(queue, workOptions, handler) : boss.work(queue, handler);
|
|
113
110
|
}
|
|
111
|
+
__name(createCNSWorker, "createCNSWorker");
|
|
114
112
|
|
|
115
113
|
// src/enqueue.ts
|
|
116
114
|
function stimulationJob(registry, collateral, payload, extra) {
|
|
117
115
|
const collateralName = registry.getCollateralName(collateral);
|
|
118
116
|
if (!collateralName) {
|
|
119
|
-
throw new Error(
|
|
120
|
-
"[@cnstra/pg-boss] Collateral is not registered in the CNSPersistOptionsRegistry; cannot enqueue it by name."
|
|
121
|
-
);
|
|
117
|
+
throw new Error("[@cnstra/pg-boss] Collateral is not registered in the CNSPersistOptionsRegistry; cannot enqueue it by name.");
|
|
122
118
|
}
|
|
123
|
-
return {
|
|
119
|
+
return {
|
|
120
|
+
collateralName,
|
|
121
|
+
payload,
|
|
122
|
+
...extra
|
|
123
|
+
};
|
|
124
124
|
}
|
|
125
|
+
__name(stimulationJob, "stimulationJob");
|
|
125
126
|
function enqueueStimulation(boss, queue, job, options) {
|
|
126
127
|
return boss.send(queue, job, options);
|
|
127
128
|
}
|
|
129
|
+
__name(enqueueStimulation, "enqueueStimulation");
|
|
128
130
|
// Annotate the CommonJS export names for ESM import in node:
|
|
129
131
|
0 && (module.exports = {
|
|
130
132
|
createCNSWorker,
|