@cnstra/pg-boss 0.1.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 ADDED
@@ -0,0 +1,86 @@
1
+ # @cnstra/pg-boss
2
+
3
+ > **⚠️ Experimental**: API may change in future versions.
4
+
5
+ [pg-boss](https://github.com/timgit/pg-boss) (Postgres-backed job queue) integration for
6
+ [CNStra](https://cnstra.org). Run each stimulation as a durable job, get Postgres-native
7
+ retry/backoff/scheduling/singleton, and stream **per-hop progress** into any store for a
8
+ live admin/history view.
9
+
10
+ It follows the same pattern as the [Message Brokers guide](https://cnstra.org/docs/integrations/message-brokers):
11
+ **one job = one stimulation**, reconstructed across processes by **name** via a
12
+ `CNSPersistOptionsRegistry` (neuron/collateral object references are not portable).
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ npm install @cnstra/pg-boss @cnstra/core pg-boss
18
+ ```
19
+
20
+ ## Worker
21
+
22
+ ```ts
23
+ import PgBoss from 'pg-boss';
24
+ import { createCNS } from '@cnstra/core';
25
+ import { createCNSWorker } from '@cnstra/pg-boss';
26
+
27
+ const { cns, registry } = createCNS({ importUserNeuron, /* … */ });
28
+
29
+ const boss = new PgBoss(process.env.DATABASE_URL!);
30
+ await boss.start();
31
+ await boss.createQueue('cns');
32
+
33
+ await createCNSWorker({
34
+ boss,
35
+ cns,
36
+ registry,
37
+ queue: 'cns',
38
+ // Optional: durably record every step. If onHop returns a Promise, CNStra
39
+ // waits for it before running the next hop (per-hop checkpoint barrier).
40
+ progress: {
41
+ onStarted: (s) => db.insertStimulation(s),
42
+ onHop: (h) => db.insertHop(h), // unique(stimulation_id, index) → idempotent
43
+ onCompleted: (s) => db.finishStimulation(s),
44
+ },
45
+ });
46
+ ```
47
+
48
+ The worker reconstructs the entry signal from the job's `collateralName`, stimulates, and
49
+ awaits completion. If the stimulation fails or aborts, `waitUntilComplete()` rejects and the
50
+ error propagates so **pg-boss applies its retry/backoff policy**.
51
+
52
+ ## Producer
53
+
54
+ ```ts
55
+ import { enqueueStimulation, stimulationJob } from '@cnstra/pg-boss';
56
+
57
+ // Type-safe: throws if the collateral isn't registered
58
+ const job = stimulationJob(registry, importUser, { userId: '42' });
59
+
60
+ await enqueueStimulation(boss, 'cns', job, {
61
+ retryLimit: 5,
62
+ retryBackoff: true,
63
+ singletonKey: 'user:42', // one in-flight stimulation per entity
64
+ });
65
+ ```
66
+
67
+ ## Retries & resume
68
+
69
+ - **Cross-process (recommended):** a retried job re-runs the whole flow from the entry signal.
70
+ Make neurons **idempotent**, or deduplicate hops with `unique(stimulation_id, index)`.
71
+ - **In-process partial resume:** `cns.activate(getFailedTasks())` works only within one process
72
+ (it holds live object references) — it is not portable through the queue.
73
+
74
+ ## What this package does / doesn't
75
+
76
+ - ✅ Job execution, retry/backoff, scheduling, singleton, concurrency → **pg-boss**.
77
+ - ✅ Per-step (hop) progress records → the `progress` sink (your tables / OIMDB / logs).
78
+ - ❌ No built-in Postgres schema or admin UI — you own the store. pg-boss has **no per-step
79
+ progress** of its own, so step history is always your tables. See the docs for a schema and
80
+ an admin-panel design.
81
+
82
+ See the full guide: https://cnstra.org/docs/integrations/pg-boss
83
+
84
+ ## License
85
+
86
+ MIT
@@ -0,0 +1,126 @@
1
+ import { ICNS, CNSPersistOptionsRegistry, CNSCollateral } from '@cnstra/core';
2
+
3
+ /**
4
+ * Minimal, structural view of the pg-boss surface this package touches.
5
+ *
6
+ * We type against these instead of importing `pg-boss` directly so the package
7
+ * builds without pg-boss installed. It is compatible with pg-boss v9/v10+ where
8
+ * `work` handlers receive an array of jobs (batch). Pass your real `PgBoss`
9
+ * instance — it satisfies this shape structurally.
10
+ */
11
+ interface IPgBossJob<TData = unknown> {
12
+ id: string;
13
+ name: string;
14
+ data: TData;
15
+ }
16
+ interface IPgBossLike {
17
+ send(name: string, data: object, options?: Record<string, unknown>): Promise<string | null>;
18
+ work<TData extends object>(name: string, handler: (jobs: IPgBossJob<TData>[]) => Promise<unknown>): Promise<string>;
19
+ work<TData extends object>(name: string, options: Record<string, unknown>, handler: (jobs: IPgBossJob<TData>[]) => Promise<unknown>): Promise<string>;
20
+ }
21
+ /**
22
+ * The payload placed on the queue. It carries the collateral **name** and a
23
+ * JSON-serializable payload — never live neuron/collateral object references,
24
+ * which are not portable across processes.
25
+ */
26
+ interface TCNSStimulationJobData {
27
+ collateralName: string;
28
+ payload: unknown;
29
+ /** Optional per-run cap on neuron hops. */
30
+ maxNeuronHops?: number;
31
+ }
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
+ /** Structural view of the response passed to `onResponse` (not exported by core). */
69
+ interface ICNSResponseLike {
70
+ inputSignal?: {
71
+ collateral?: unknown;
72
+ payload?: unknown;
73
+ };
74
+ outputSignal?: {
75
+ collateral?: unknown;
76
+ payload?: unknown;
77
+ };
78
+ error?: unknown;
79
+ }
80
+
81
+ interface TCNSWorkerOptions {
82
+ /** Your pg-boss instance (already started). */
83
+ boss: IPgBossLike;
84
+ /** The CNS the jobs run against. */
85
+ cns: ICNS<any, any>;
86
+ /** Name ↔ object registry used to reconstruct signals from job data. */
87
+ registry: CNSPersistOptionsRegistry;
88
+ /** Queue name to consume. */
89
+ queue: string;
90
+ /** Optional durable progress sink (started / hop / completed). */
91
+ progress?: ICNSProgressSink;
92
+ /** pg-boss `work` options (batchSize, pollingIntervalSeconds, …). */
93
+ workOptions?: Record<string, unknown>;
94
+ }
95
+ /**
96
+ * Register a pg-boss worker that turns each job into a CNStra stimulation.
97
+ *
98
+ * One job = one stimulation. The job carries `{ collateralName, payload }`; the
99
+ * worker reconstructs the entry signal by name, stimulates, optionally streams
100
+ * per-hop progress, and awaits completion. If the stimulation fails or aborts,
101
+ * `waitUntilComplete()` rejects and the error propagates so pg-boss applies its
102
+ * own retry/backoff policy.
103
+ */
104
+ declare function createCNSWorker(options: TCNSWorkerOptions): Promise<string>;
105
+
106
+ /** Commonly used pg-boss send options (a superset is passed through). */
107
+ interface TCNSSendOptions {
108
+ retryLimit?: number;
109
+ retryBackoff?: boolean;
110
+ retryDelay?: number;
111
+ /** One in-flight job per key — e.g. one stimulation per entity id. */
112
+ singletonKey?: string;
113
+ startAfter?: number | string | Date;
114
+ expireInSeconds?: number;
115
+ priority?: number;
116
+ [key: string]: unknown;
117
+ }
118
+ /**
119
+ * Build a queue job from a **registered** collateral. Throws if the collateral
120
+ * is not in the registry, so a typo can't reach the queue.
121
+ */
122
+ declare function stimulationJob(registry: CNSPersistOptionsRegistry, collateral: CNSCollateral<unknown>, payload: unknown, extra?: Pick<TCNSStimulationJobData, 'maxNeuronHops'>): TCNSStimulationJobData;
123
+ /** Send a stimulation job to a pg-boss queue. Returns the job id. */
124
+ declare function enqueueStimulation(boss: IPgBossLike, queue: string, job: TCNSStimulationJobData, options?: TCNSSendOptions): Promise<string | null>;
125
+
126
+ export { type ICNSProgressSink, type ICNSResponseLike, type IPgBossJob, type IPgBossLike, type TCNSHopRecord, type TCNSSendOptions, type TCNSStimulationJobData, type TCNSStimulationLifecycle, type TCNSWorkerOptions, createCNSWorker, enqueueStimulation, stimulationJob };
@@ -0,0 +1,126 @@
1
+ import { ICNS, CNSPersistOptionsRegistry, CNSCollateral } from '@cnstra/core';
2
+
3
+ /**
4
+ * Minimal, structural view of the pg-boss surface this package touches.
5
+ *
6
+ * We type against these instead of importing `pg-boss` directly so the package
7
+ * builds without pg-boss installed. It is compatible with pg-boss v9/v10+ where
8
+ * `work` handlers receive an array of jobs (batch). Pass your real `PgBoss`
9
+ * instance — it satisfies this shape structurally.
10
+ */
11
+ interface IPgBossJob<TData = unknown> {
12
+ id: string;
13
+ name: string;
14
+ data: TData;
15
+ }
16
+ interface IPgBossLike {
17
+ send(name: string, data: object, options?: Record<string, unknown>): Promise<string | null>;
18
+ work<TData extends object>(name: string, handler: (jobs: IPgBossJob<TData>[]) => Promise<unknown>): Promise<string>;
19
+ work<TData extends object>(name: string, options: Record<string, unknown>, handler: (jobs: IPgBossJob<TData>[]) => Promise<unknown>): Promise<string>;
20
+ }
21
+ /**
22
+ * The payload placed on the queue. It carries the collateral **name** and a
23
+ * JSON-serializable payload — never live neuron/collateral object references,
24
+ * which are not portable across processes.
25
+ */
26
+ interface TCNSStimulationJobData {
27
+ collateralName: string;
28
+ payload: unknown;
29
+ /** Optional per-run cap on neuron hops. */
30
+ maxNeuronHops?: number;
31
+ }
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
+ /** Structural view of the response passed to `onResponse` (not exported by core). */
69
+ interface ICNSResponseLike {
70
+ inputSignal?: {
71
+ collateral?: unknown;
72
+ payload?: unknown;
73
+ };
74
+ outputSignal?: {
75
+ collateral?: unknown;
76
+ payload?: unknown;
77
+ };
78
+ error?: unknown;
79
+ }
80
+
81
+ interface TCNSWorkerOptions {
82
+ /** Your pg-boss instance (already started). */
83
+ boss: IPgBossLike;
84
+ /** The CNS the jobs run against. */
85
+ cns: ICNS<any, any>;
86
+ /** Name ↔ object registry used to reconstruct signals from job data. */
87
+ registry: CNSPersistOptionsRegistry;
88
+ /** Queue name to consume. */
89
+ queue: string;
90
+ /** Optional durable progress sink (started / hop / completed). */
91
+ progress?: ICNSProgressSink;
92
+ /** pg-boss `work` options (batchSize, pollingIntervalSeconds, …). */
93
+ workOptions?: Record<string, unknown>;
94
+ }
95
+ /**
96
+ * Register a pg-boss worker that turns each job into a CNStra stimulation.
97
+ *
98
+ * One job = one stimulation. The job carries `{ collateralName, payload }`; the
99
+ * worker reconstructs the entry signal by name, stimulates, optionally streams
100
+ * per-hop progress, and awaits completion. If the stimulation fails or aborts,
101
+ * `waitUntilComplete()` rejects and the error propagates so pg-boss applies its
102
+ * own retry/backoff policy.
103
+ */
104
+ declare function createCNSWorker(options: TCNSWorkerOptions): Promise<string>;
105
+
106
+ /** Commonly used pg-boss send options (a superset is passed through). */
107
+ interface TCNSSendOptions {
108
+ retryLimit?: number;
109
+ retryBackoff?: boolean;
110
+ retryDelay?: number;
111
+ /** One in-flight job per key — e.g. one stimulation per entity id. */
112
+ singletonKey?: string;
113
+ startAfter?: number | string | Date;
114
+ expireInSeconds?: number;
115
+ priority?: number;
116
+ [key: string]: unknown;
117
+ }
118
+ /**
119
+ * Build a queue job from a **registered** collateral. Throws if the collateral
120
+ * is not in the registry, so a typo can't reach the queue.
121
+ */
122
+ declare function stimulationJob(registry: CNSPersistOptionsRegistry, collateral: CNSCollateral<unknown>, payload: unknown, extra?: Pick<TCNSStimulationJobData, 'maxNeuronHops'>): TCNSStimulationJobData;
123
+ /** Send a stimulation job to a pg-boss queue. Returns the job id. */
124
+ declare function enqueueStimulation(boss: IPgBossLike, queue: string, job: TCNSStimulationJobData, options?: TCNSSendOptions): Promise<string | null>;
125
+
126
+ export { type ICNSProgressSink, type ICNSResponseLike, type IPgBossJob, type IPgBossLike, type TCNSHopRecord, type TCNSSendOptions, type TCNSStimulationJobData, type TCNSStimulationLifecycle, type TCNSWorkerOptions, createCNSWorker, enqueueStimulation, stimulationJob };
package/dist/index.js ADDED
@@ -0,0 +1,134 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/index.ts
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
+ createCNSWorker: () => createCNSWorker,
23
+ enqueueStimulation: () => enqueueStimulation,
24
+ stimulationJob: () => stimulationJob
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/worker.ts
29
+ function toHopRecord(jobId, index, resp, cns, registry) {
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
+ }
46
+ function createCNSWorker(options) {
47
+ const { boss, cns, registry, queue, progress, workOptions } = options;
48
+ const runJob = async (job) => {
49
+ var _a, _b, _c;
50
+ const { collateralName, payload, maxNeuronHops } = job.data;
51
+ const collateral = registry.getCollateral(collateralName);
52
+ if (!collateral) {
53
+ throw new Error(
54
+ `[@cnstra/pg-boss] Unknown collateral "${collateralName}". Register it in the CNSPersistOptionsRegistry.`
55
+ );
56
+ }
57
+ const startedAt = Date.now();
58
+ let hopCount = 0;
59
+ await ((_a = progress == null ? void 0 : progress.onStarted) == null ? void 0 : _a.call(progress, {
60
+ jobId: job.id,
61
+ collateralName,
62
+ payload,
63
+ status: "running",
64
+ startedAt,
65
+ hopCount: 0
66
+ }));
67
+ const stimulation = cns.stimulate(collateral.createSignal(payload), {
68
+ maxNeuronHops,
69
+ onResponse: async (resp) => {
70
+ var _a2;
71
+ const rec = toHopRecord(
72
+ job.id,
73
+ hopCount,
74
+ resp,
75
+ cns,
76
+ registry
77
+ );
78
+ hopCount += 1;
79
+ await ((_a2 = progress == null ? void 0 : progress.onHop) == null ? void 0 : _a2.call(progress, rec));
80
+ }
81
+ });
82
+ try {
83
+ await stimulation.waitUntilComplete();
84
+ await ((_b = progress == null ? void 0 : progress.onCompleted) == null ? void 0 : _b.call(progress, {
85
+ jobId: job.id,
86
+ collateralName,
87
+ payload,
88
+ status: "completed",
89
+ startedAt,
90
+ completedAt: Date.now(),
91
+ hopCount
92
+ }));
93
+ } catch (err) {
94
+ await ((_c = progress == null ? void 0 : progress.onCompleted) == null ? void 0 : _c.call(progress, {
95
+ jobId: job.id,
96
+ collateralName,
97
+ payload,
98
+ status: "failed",
99
+ startedAt,
100
+ completedAt: Date.now(),
101
+ hopCount,
102
+ error: err instanceof Error ? err.message : String(err)
103
+ }));
104
+ throw err;
105
+ }
106
+ };
107
+ const handler = async (jobs) => {
108
+ for (const job of jobs) {
109
+ await runJob(job);
110
+ }
111
+ };
112
+ return workOptions ? boss.work(queue, workOptions, handler) : boss.work(queue, handler);
113
+ }
114
+
115
+ // src/enqueue.ts
116
+ function stimulationJob(registry, collateral, payload, extra) {
117
+ const collateralName = registry.getCollateralName(collateral);
118
+ if (!collateralName) {
119
+ throw new Error(
120
+ "[@cnstra/pg-boss] Collateral is not registered in the CNSPersistOptionsRegistry; cannot enqueue it by name."
121
+ );
122
+ }
123
+ return { collateralName, payload, ...extra };
124
+ }
125
+ function enqueueStimulation(boss, queue, job, options) {
126
+ return boss.send(queue, job, options);
127
+ }
128
+ // Annotate the CommonJS export names for ESM import in node:
129
+ 0 && (module.exports = {
130
+ createCNSWorker,
131
+ enqueueStimulation,
132
+ stimulationJob
133
+ });
134
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/worker.ts","../src/enqueue.ts"],"sourcesContent":["export { createCNSWorker } from './worker';\nexport type { TCNSWorkerOptions } from './worker';\n\nexport { enqueueStimulation, stimulationJob } from './enqueue';\nexport type { TCNSSendOptions } from './enqueue';\n\nexport type {\n IPgBossLike,\n IPgBossJob,\n TCNSStimulationJobData,\n TCNSHopRecord,\n TCNSStimulationLifecycle,\n ICNSProgressSink,\n ICNSResponseLike,\n} from './types';\n","import type { CNSPersistOptionsRegistry, ICNS } from '@cnstra/core';\nimport type {\n IPgBossLike,\n IPgBossJob,\n ICNSProgressSink,\n ICNSResponseLike,\n TCNSHopRecord,\n TCNSStimulationJobData,\n} from './types';\n\nexport interface TCNSWorkerOptions {\n /** Your pg-boss instance (already started). */\n boss: IPgBossLike;\n /** The CNS the jobs run against. */\n cns: ICNS<any, any>;\n /** Name ↔ object registry used to reconstruct signals from job data. */\n registry: CNSPersistOptionsRegistry;\n /** Queue name to consume. */\n queue: string;\n /** Optional durable progress sink (started / hop / completed). */\n progress?: ICNSProgressSink;\n /** pg-boss `work` options (batchSize, pollingIntervalSeconds, …). */\n workOptions?: Record<string, unknown>;\n}\n\n/**\n * Resolve a single response into a durable hop record, turning live object\n * references into stable names via the registry (same derivation devtools uses).\n */\nfunction toHopRecord(\n jobId: string,\n index: number,\n resp: ICNSResponseLike,\n cns: ICNS<any, any>,\n registry: CNSPersistOptionsRegistry\n): TCNSHopRecord {\n const outputCol = resp.outputSignal?.collateral;\n const inputCol = resp.inputSignal?.collateral;\n\n const ownerNeuron = outputCol\n ? cns.network.getParentNeuronByCollateral(outputCol as any)\n : null;\n\n return {\n jobId,\n index,\n neuronName: ownerNeuron\n ? registry.getNeuronName(ownerNeuron as any) ?? null\n : null,\n inputCollateral: inputCol\n ? registry.getCollateralName(inputCol as any) ?? null\n : null,\n outputCollateral: outputCol\n ? registry.getCollateralName(outputCol as any) ?? null\n : null,\n inputPayload:\n resp.inputSignal?.payload ?? resp.outputSignal?.payload ?? null,\n outputPayload: outputCol ? resp.outputSignal?.payload ?? null : null,\n error: resp.error != null ? String(resp.error) : null,\n at: Date.now(),\n };\n}\n\n/**\n * Register a pg-boss worker that turns each job into a CNStra stimulation.\n *\n * One job = one stimulation. The job carries `{ collateralName, payload }`; the\n * worker reconstructs the entry signal by name, stimulates, optionally streams\n * per-hop progress, and awaits completion. If the stimulation fails or aborts,\n * `waitUntilComplete()` rejects and the error propagates so pg-boss applies its\n * own retry/backoff policy.\n */\nexport function createCNSWorker(options: TCNSWorkerOptions): Promise<string> {\n const { boss, cns, registry, queue, progress, workOptions } = options;\n\n const runJob = async (\n job: IPgBossJob<TCNSStimulationJobData>\n ): Promise<void> => {\n const { collateralName, payload, maxNeuronHops } = job.data;\n const collateral = registry.getCollateral(collateralName);\n if (!collateral) {\n throw new Error(\n `[@cnstra/pg-boss] Unknown collateral \"${collateralName}\". ` +\n `Register it in the CNSPersistOptionsRegistry.`\n );\n }\n\n const startedAt = Date.now();\n let hopCount = 0;\n\n await progress?.onStarted?.({\n jobId: job.id,\n collateralName,\n payload,\n status: 'running',\n startedAt,\n hopCount: 0,\n });\n\n const stimulation = cns.stimulate(collateral.createSignal(payload), {\n maxNeuronHops,\n onResponse: async (resp: ICNSResponseLike) => {\n const rec = toHopRecord(\n job.id,\n hopCount,\n resp,\n cns,\n registry\n );\n hopCount += 1;\n // Returning a Promise makes CNStra wait for the durable write\n // before enqueuing the next hop (per-hop checkpoint barrier).\n await progress?.onHop?.(rec);\n },\n });\n\n try {\n await stimulation.waitUntilComplete();\n await progress?.onCompleted?.({\n jobId: job.id,\n collateralName,\n payload,\n status: 'completed',\n startedAt,\n completedAt: Date.now(),\n hopCount,\n });\n } catch (err) {\n await progress?.onCompleted?.({\n jobId: job.id,\n collateralName,\n payload,\n status: 'failed',\n startedAt,\n completedAt: Date.now(),\n hopCount,\n error: err instanceof Error ? err.message : String(err),\n });\n // Let pg-boss decide about retries/backoff.\n throw err;\n }\n };\n\n const handler = async (\n jobs: IPgBossJob<TCNSStimulationJobData>[]\n ): Promise<void> => {\n for (const job of jobs) {\n await runJob(job);\n }\n };\n\n return workOptions\n ? boss.work<TCNSStimulationJobData>(queue, workOptions, handler)\n : boss.work<TCNSStimulationJobData>(queue, handler);\n}\n","import type { CNSCollateral, CNSPersistOptionsRegistry } from '@cnstra/core';\nimport type { IPgBossLike, TCNSStimulationJobData } from './types';\n\n/** Commonly used pg-boss send options (a superset is passed through). */\nexport interface TCNSSendOptions {\n retryLimit?: number;\n retryBackoff?: boolean;\n retryDelay?: number;\n /** One in-flight job per key — e.g. one stimulation per entity id. */\n singletonKey?: string;\n startAfter?: number | string | Date;\n expireInSeconds?: number;\n priority?: number;\n [key: string]: unknown;\n}\n\n/**\n * Build a queue job from a **registered** collateral. Throws if the collateral\n * is not in the registry, so a typo can't reach the queue.\n */\nexport function stimulationJob(\n registry: CNSPersistOptionsRegistry,\n collateral: CNSCollateral<unknown>,\n payload: unknown,\n extra?: Pick<TCNSStimulationJobData, 'maxNeuronHops'>\n): TCNSStimulationJobData {\n const collateralName = registry.getCollateralName(collateral);\n if (!collateralName) {\n throw new Error(\n '[@cnstra/pg-boss] Collateral is not registered in the ' +\n 'CNSPersistOptionsRegistry; cannot enqueue it by name.'\n );\n }\n return { collateralName, payload, ...extra };\n}\n\n/** Send a stimulation job to a pg-boss queue. Returns the job id. */\nexport function enqueueStimulation(\n boss: IPgBossLike,\n queue: string,\n job: TCNSStimulationJobData,\n options?: TCNSSendOptions\n): Promise<string | null> {\n return boss.send(queue, job as unknown as object, options);\n}\n"],"mappings":"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","names":["_a"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,106 @@
1
+ // src/worker.ts
2
+ function toHopRecord(jobId, index, resp, cns, registry) {
3
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
4
+ const outputCol = (_a = resp.outputSignal) == null ? void 0 : _a.collateral;
5
+ const inputCol = (_b = resp.inputSignal) == null ? void 0 : _b.collateral;
6
+ const ownerNeuron = outputCol ? cns.network.getParentNeuronByCollateral(outputCol) : null;
7
+ return {
8
+ jobId,
9
+ index,
10
+ neuronName: ownerNeuron ? (_c = registry.getNeuronName(ownerNeuron)) != null ? _c : null : null,
11
+ inputCollateral: inputCol ? (_d = registry.getCollateralName(inputCol)) != null ? _d : null : null,
12
+ outputCollateral: outputCol ? (_e = registry.getCollateralName(outputCol)) != null ? _e : null : null,
13
+ inputPayload: (_i = (_h = (_f = resp.inputSignal) == null ? void 0 : _f.payload) != null ? _h : (_g = resp.outputSignal) == null ? void 0 : _g.payload) != null ? _i : null,
14
+ outputPayload: outputCol ? (_k = (_j = resp.outputSignal) == null ? void 0 : _j.payload) != null ? _k : null : null,
15
+ error: resp.error != null ? String(resp.error) : null,
16
+ at: Date.now()
17
+ };
18
+ }
19
+ function createCNSWorker(options) {
20
+ const { boss, cns, registry, queue, progress, workOptions } = options;
21
+ const runJob = async (job) => {
22
+ var _a, _b, _c;
23
+ const { collateralName, payload, maxNeuronHops } = job.data;
24
+ const collateral = registry.getCollateral(collateralName);
25
+ if (!collateral) {
26
+ throw new Error(
27
+ `[@cnstra/pg-boss] Unknown collateral "${collateralName}". Register it in the CNSPersistOptionsRegistry.`
28
+ );
29
+ }
30
+ const startedAt = Date.now();
31
+ let hopCount = 0;
32
+ await ((_a = progress == null ? void 0 : progress.onStarted) == null ? void 0 : _a.call(progress, {
33
+ jobId: job.id,
34
+ collateralName,
35
+ payload,
36
+ status: "running",
37
+ startedAt,
38
+ hopCount: 0
39
+ }));
40
+ const stimulation = cns.stimulate(collateral.createSignal(payload), {
41
+ maxNeuronHops,
42
+ onResponse: async (resp) => {
43
+ var _a2;
44
+ const rec = toHopRecord(
45
+ job.id,
46
+ hopCount,
47
+ resp,
48
+ cns,
49
+ registry
50
+ );
51
+ hopCount += 1;
52
+ await ((_a2 = progress == null ? void 0 : progress.onHop) == null ? void 0 : _a2.call(progress, rec));
53
+ }
54
+ });
55
+ try {
56
+ await stimulation.waitUntilComplete();
57
+ await ((_b = progress == null ? void 0 : progress.onCompleted) == null ? void 0 : _b.call(progress, {
58
+ jobId: job.id,
59
+ collateralName,
60
+ payload,
61
+ status: "completed",
62
+ startedAt,
63
+ completedAt: Date.now(),
64
+ hopCount
65
+ }));
66
+ } catch (err) {
67
+ await ((_c = progress == null ? void 0 : progress.onCompleted) == null ? void 0 : _c.call(progress, {
68
+ jobId: job.id,
69
+ collateralName,
70
+ payload,
71
+ status: "failed",
72
+ startedAt,
73
+ completedAt: Date.now(),
74
+ hopCount,
75
+ error: err instanceof Error ? err.message : String(err)
76
+ }));
77
+ throw err;
78
+ }
79
+ };
80
+ const handler = async (jobs) => {
81
+ for (const job of jobs) {
82
+ await runJob(job);
83
+ }
84
+ };
85
+ return workOptions ? boss.work(queue, workOptions, handler) : boss.work(queue, handler);
86
+ }
87
+
88
+ // src/enqueue.ts
89
+ function stimulationJob(registry, collateral, payload, extra) {
90
+ const collateralName = registry.getCollateralName(collateral);
91
+ if (!collateralName) {
92
+ throw new Error(
93
+ "[@cnstra/pg-boss] Collateral is not registered in the CNSPersistOptionsRegistry; cannot enqueue it by name."
94
+ );
95
+ }
96
+ return { collateralName, payload, ...extra };
97
+ }
98
+ function enqueueStimulation(boss, queue, job, options) {
99
+ return boss.send(queue, job, options);
100
+ }
101
+ export {
102
+ createCNSWorker,
103
+ enqueueStimulation,
104
+ stimulationJob
105
+ };
106
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/worker.ts","../src/enqueue.ts"],"sourcesContent":["import type { CNSPersistOptionsRegistry, ICNS } from '@cnstra/core';\nimport type {\n IPgBossLike,\n IPgBossJob,\n ICNSProgressSink,\n ICNSResponseLike,\n TCNSHopRecord,\n TCNSStimulationJobData,\n} from './types';\n\nexport interface TCNSWorkerOptions {\n /** Your pg-boss instance (already started). */\n boss: IPgBossLike;\n /** The CNS the jobs run against. */\n cns: ICNS<any, any>;\n /** Name ↔ object registry used to reconstruct signals from job data. */\n registry: CNSPersistOptionsRegistry;\n /** Queue name to consume. */\n queue: string;\n /** Optional durable progress sink (started / hop / completed). */\n progress?: ICNSProgressSink;\n /** pg-boss `work` options (batchSize, pollingIntervalSeconds, …). */\n workOptions?: Record<string, unknown>;\n}\n\n/**\n * Resolve a single response into a durable hop record, turning live object\n * references into stable names via the registry (same derivation devtools uses).\n */\nfunction toHopRecord(\n jobId: string,\n index: number,\n resp: ICNSResponseLike,\n cns: ICNS<any, any>,\n registry: CNSPersistOptionsRegistry\n): TCNSHopRecord {\n const outputCol = resp.outputSignal?.collateral;\n const inputCol = resp.inputSignal?.collateral;\n\n const ownerNeuron = outputCol\n ? cns.network.getParentNeuronByCollateral(outputCol as any)\n : null;\n\n return {\n jobId,\n index,\n neuronName: ownerNeuron\n ? registry.getNeuronName(ownerNeuron as any) ?? null\n : null,\n inputCollateral: inputCol\n ? registry.getCollateralName(inputCol as any) ?? null\n : null,\n outputCollateral: outputCol\n ? registry.getCollateralName(outputCol as any) ?? null\n : null,\n inputPayload:\n resp.inputSignal?.payload ?? resp.outputSignal?.payload ?? null,\n outputPayload: outputCol ? resp.outputSignal?.payload ?? null : null,\n error: resp.error != null ? String(resp.error) : null,\n at: Date.now(),\n };\n}\n\n/**\n * Register a pg-boss worker that turns each job into a CNStra stimulation.\n *\n * One job = one stimulation. The job carries `{ collateralName, payload }`; the\n * worker reconstructs the entry signal by name, stimulates, optionally streams\n * per-hop progress, and awaits completion. If the stimulation fails or aborts,\n * `waitUntilComplete()` rejects and the error propagates so pg-boss applies its\n * own retry/backoff policy.\n */\nexport function createCNSWorker(options: TCNSWorkerOptions): Promise<string> {\n const { boss, cns, registry, queue, progress, workOptions } = options;\n\n const runJob = async (\n job: IPgBossJob<TCNSStimulationJobData>\n ): Promise<void> => {\n const { collateralName, payload, maxNeuronHops } = job.data;\n const collateral = registry.getCollateral(collateralName);\n if (!collateral) {\n throw new Error(\n `[@cnstra/pg-boss] Unknown collateral \"${collateralName}\". ` +\n `Register it in the CNSPersistOptionsRegistry.`\n );\n }\n\n const startedAt = Date.now();\n let hopCount = 0;\n\n await progress?.onStarted?.({\n jobId: job.id,\n collateralName,\n payload,\n status: 'running',\n startedAt,\n hopCount: 0,\n });\n\n const stimulation = cns.stimulate(collateral.createSignal(payload), {\n maxNeuronHops,\n onResponse: async (resp: ICNSResponseLike) => {\n const rec = toHopRecord(\n job.id,\n hopCount,\n resp,\n cns,\n registry\n );\n hopCount += 1;\n // Returning a Promise makes CNStra wait for the durable write\n // before enqueuing the next hop (per-hop checkpoint barrier).\n await progress?.onHop?.(rec);\n },\n });\n\n try {\n await stimulation.waitUntilComplete();\n await progress?.onCompleted?.({\n jobId: job.id,\n collateralName,\n payload,\n status: 'completed',\n startedAt,\n completedAt: Date.now(),\n hopCount,\n });\n } catch (err) {\n await progress?.onCompleted?.({\n jobId: job.id,\n collateralName,\n payload,\n status: 'failed',\n startedAt,\n completedAt: Date.now(),\n hopCount,\n error: err instanceof Error ? err.message : String(err),\n });\n // Let pg-boss decide about retries/backoff.\n throw err;\n }\n };\n\n const handler = async (\n jobs: IPgBossJob<TCNSStimulationJobData>[]\n ): Promise<void> => {\n for (const job of jobs) {\n await runJob(job);\n }\n };\n\n return workOptions\n ? boss.work<TCNSStimulationJobData>(queue, workOptions, handler)\n : boss.work<TCNSStimulationJobData>(queue, handler);\n}\n","import type { CNSCollateral, CNSPersistOptionsRegistry } from '@cnstra/core';\nimport type { IPgBossLike, TCNSStimulationJobData } from './types';\n\n/** Commonly used pg-boss send options (a superset is passed through). */\nexport interface TCNSSendOptions {\n retryLimit?: number;\n retryBackoff?: boolean;\n retryDelay?: number;\n /** One in-flight job per key — e.g. one stimulation per entity id. */\n singletonKey?: string;\n startAfter?: number | string | Date;\n expireInSeconds?: number;\n priority?: number;\n [key: string]: unknown;\n}\n\n/**\n * Build a queue job from a **registered** collateral. Throws if the collateral\n * is not in the registry, so a typo can't reach the queue.\n */\nexport function stimulationJob(\n registry: CNSPersistOptionsRegistry,\n collateral: CNSCollateral<unknown>,\n payload: unknown,\n extra?: Pick<TCNSStimulationJobData, 'maxNeuronHops'>\n): TCNSStimulationJobData {\n const collateralName = registry.getCollateralName(collateral);\n if (!collateralName) {\n throw new Error(\n '[@cnstra/pg-boss] Collateral is not registered in the ' +\n 'CNSPersistOptionsRegistry; cannot enqueue it by name.'\n );\n }\n return { collateralName, payload, ...extra };\n}\n\n/** Send a stimulation job to a pg-boss queue. Returns the job id. */\nexport function enqueueStimulation(\n boss: IPgBossLike,\n queue: string,\n job: TCNSStimulationJobData,\n options?: TCNSSendOptions\n): Promise<string | null> {\n return boss.send(queue, job as unknown as object, options);\n}\n"],"mappings":"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","names":["_a"]}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@cnstra/pg-boss",
3
+ "version": "0.1.0",
4
+ "description": "pg-boss (Postgres) integration for CNStra: run stimulations as jobs and stream per-hop progress",
5
+ "keywords": [
6
+ "cnstra",
7
+ "pg-boss",
8
+ "postgres",
9
+ "queue",
10
+ "workflow",
11
+ "orchestration"
12
+ ],
13
+ "main": "dist/index.js",
14
+ "module": "dist/index.mjs",
15
+ "types": "dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.mjs",
20
+ "require": "./dist/index.js"
21
+ }
22
+ },
23
+ "sideEffects": false,
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "scripts": {
28
+ "build": "tsup",
29
+ "test:types": "tsc --noEmit",
30
+ "clean": "rm -rf dist"
31
+ },
32
+ "peerDependencies": {
33
+ "@cnstra/core": "^2.4.0",
34
+ "pg-boss": ">=9"
35
+ },
36
+ "peerDependenciesMeta": {
37
+ "pg-boss": {
38
+ "optional": true
39
+ }
40
+ },
41
+ "devDependencies": {
42
+ "@cnstra/core": "^2.4.0",
43
+ "tsup": "8.5.1",
44
+ "typescript": "5.7.2"
45
+ },
46
+ "author": "Andrei Baikov <abaikov23@gmail.com>",
47
+ "license": "MIT",
48
+ "publishConfig": {
49
+ "access": "public"
50
+ }
51
+ }