@powerhousedao/reactor 6.2.3-dev.5 → 6.2.3-dev.50
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/dist/document-indexer-DwAMDVRI.js +1844 -0
- package/dist/document-indexer-DwAMDVRI.js.map +1 -0
- package/dist/drive-container-types-Ci1pdv4X.js +3766 -0
- package/dist/drive-container-types-Ci1pdv4X.js.map +1 -0
- package/dist/entry.d.ts +2 -1
- package/dist/entry.js +111 -7
- package/dist/entry.js.map +1 -1
- package/dist/{errors-D3S6Eysd.js → errors-BM_ULVWd.js} +9 -1
- package/dist/{errors-D3S6Eysd.js.map → errors-BM_ULVWd.js.map} +1 -1
- package/dist/forwarding-logger-ByfBFgMS.js +3635 -0
- package/dist/forwarding-logger-ByfBFgMS.js.map +1 -0
- package/dist/index-CNhT69De.d.ts +6383 -0
- package/dist/index-CNhT69De.d.ts.map +1 -0
- package/dist/index.d.ts +935 -5509
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5189 -1022
- package/dist/index.js.map +1 -1
- package/dist/load-spec-ZLjuyhxz.js +246 -0
- package/dist/load-spec-ZLjuyhxz.js.map +1 -0
- package/dist/projection-entry.d.ts +2 -1
- package/dist/projection-entry.js +99 -21
- package/dist/projection-entry.js.map +1 -1
- package/dist/{projection-shard-manager-CPQc5XHL.js → projection-shard-manager-CQ5FwQmv.js} +24 -4
- package/dist/projection-shard-manager-CQ5FwQmv.js.map +1 -0
- package/dist/{projection-worker-wI4PwcV2.js → projection-worker-D8uNFdwX.js} +1 -1
- package/dist/{projection-worker-wI4PwcV2.js.map → projection-worker-D8uNFdwX.js.map} +1 -1
- package/dist/rpc.d.ts +332 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +571 -0
- package/dist/rpc.js.map +1 -0
- package/dist/{transport-CuogVKN_.js → transport-B3G50KVd.js} +1 -1
- package/dist/{transport-CuogVKN_.js.map → transport-B3G50KVd.js.map} +1 -1
- package/dist/{transport-ByGviWdZ.js → transport-CZDHzfvy.js} +1 -1
- package/dist/{transport-ByGviWdZ.js.map → transport-CZDHzfvy.js.map} +1 -1
- package/dist/{worker-handle-CrERzl8s.js → worker-handle-CN2-oRv-.js} +30 -17
- package/dist/worker-handle-CN2-oRv-.js.map +1 -0
- package/package.json +34 -18
- package/dist/build-worker-executor-DnU3ZU4H.js +0 -83
- package/dist/build-worker-executor-DnU3ZU4H.js.map +0 -1
- package/dist/document-indexer-C5Gsa1B3.js +0 -958
- package/dist/document-indexer-C5Gsa1B3.js.map +0 -1
- package/dist/drive-container-types-yZrksiJR.js +0 -5310
- package/dist/drive-container-types-yZrksiJR.js.map +0 -1
- package/dist/error-info-Cpu4OY3o.js +0 -62
- package/dist/error-info-Cpu4OY3o.js.map +0 -1
- package/dist/forwarding-logger-BBkMSxuJ.js +0 -85
- package/dist/forwarding-logger-BBkMSxuJ.js.map +0 -1
- package/dist/projection-shard-manager-CPQc5XHL.js.map +0 -1
- package/dist/types-DMKLa0Ok.js +0 -33
- package/dist/types-DMKLa0Ok.js.map +0 -1
- package/dist/worker-HPysBfhx.js +0 -22
- package/dist/worker-HPysBfhx.js.map +0 -1
- package/dist/worker-handle-CrERzl8s.js.map +0 -1
package/dist/entry.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
|
2
|
+
export {};
|
package/dist/entry.js
CHANGED
|
@@ -1,8 +1,103 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as
|
|
3
|
-
import { n as
|
|
1
|
+
import { D as CollectionMembershipCache, E as DocumentMetaCache, St as ReactorEventTypes, a as REACTOR_SCHEMA, d as KyselyKeyframeStore, f as EventBus, l as instrumentPgPool, m as KyselyOperationIndex, n as errorToInfo, p as KyselyWriteCache, t as createForwardingLogger, u as KyselyOperationStore } from "./forwarding-logger-ByfBFgMS.js";
|
|
2
|
+
import { a as KyselyExecutionScope, n as SimpleJobExecutor, t as DEFAULT_DRIVE_CONTAINER_TYPES } from "./drive-container-types-Ci1pdv4X.js";
|
|
3
|
+
import { n as loadDocumentModelSpec, r as DocumentModelRegistry, t as defaultLoadFactory } from "./load-spec-ZLjuyhxz.js";
|
|
4
4
|
import { ConsoleLogger } from "document-model";
|
|
5
5
|
import { isMainThread, parentPort } from "node:worker_threads";
|
|
6
|
+
//#region src/executor/worker/build-worker-executor.ts
|
|
7
|
+
async function loadModelManifest(entries, loadFactory, registry, logger) {
|
|
8
|
+
for (const entry of entries) {
|
|
9
|
+
let module;
|
|
10
|
+
try {
|
|
11
|
+
module = await loadFactory(entry.spec);
|
|
12
|
+
} catch (error) {
|
|
13
|
+
logger.error("worker failed to load document model: @entry @error", entry, error);
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
const [result] = registry.registerModules(module);
|
|
17
|
+
if (result.status === "error") {
|
|
18
|
+
logger.error("worker failed to register document model: @entry @error", entry, result.error);
|
|
19
|
+
throw result.error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Assembles the in-worker storage stack plus a {@link SimpleJobExecutor}
|
|
25
|
+
* bound to a pre-built Kysely instance. The parent owns the wire protocol
|
|
26
|
+
* and routing; the worker owns everything below `SimpleJobExecutor`.
|
|
27
|
+
*
|
|
28
|
+
* The local event bus exists only to satisfy the executor's contract: its
|
|
29
|
+
* JOB_WRITE_READY emissions are captured here and shipped to the parent
|
|
30
|
+
* via {@link WorkerExecutorStack.takeLastWriteReady}.
|
|
31
|
+
*/
|
|
32
|
+
async function buildWorkerExecutor(options) {
|
|
33
|
+
const { init, database: baseDatabase, logger } = options;
|
|
34
|
+
const driveContainerTypes = options.driveContainerTypes ?? DEFAULT_DRIVE_CONTAINER_TYPES;
|
|
35
|
+
const loadFactory = options.loadFactory ?? defaultLoadFactory;
|
|
36
|
+
const registry = new DocumentModelRegistry();
|
|
37
|
+
await loadModelManifest(init.models, loadFactory, registry, logger);
|
|
38
|
+
let signer;
|
|
39
|
+
if (init.signer) try {
|
|
40
|
+
signer = await loadFactory(init.signer);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
logger.error("worker failed to load signer: @spec @error", init.signer.module, error);
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
let trustPolicy;
|
|
46
|
+
if (init.trustPolicy) try {
|
|
47
|
+
trustPolicy = await loadFactory(init.trustPolicy);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
logger.error("worker failed to load trust policy: @spec @error", init.trustPolicy.module, error);
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
const database = baseDatabase.withSchema(REACTOR_SCHEMA);
|
|
53
|
+
const operationStore = new KyselyOperationStore(database);
|
|
54
|
+
const keyframeStore = new KyselyKeyframeStore(database);
|
|
55
|
+
const writeCache = new KyselyWriteCache(keyframeStore, operationStore, registry, {
|
|
56
|
+
maxDocuments: 100,
|
|
57
|
+
ringBufferSize: 10,
|
|
58
|
+
keyframeInterval: 10
|
|
59
|
+
});
|
|
60
|
+
await writeCache.startup();
|
|
61
|
+
const operationIndex = new KyselyOperationIndex(database);
|
|
62
|
+
const documentMetaCache = new DocumentMetaCache(operationStore, { maxDocuments: 1e3 });
|
|
63
|
+
await documentMetaCache.startup();
|
|
64
|
+
const collectionMembershipCache = new CollectionMembershipCache(operationIndex);
|
|
65
|
+
const executionScope = new KyselyExecutionScope(database, operationStore, operationIndex, keyframeStore, writeCache, documentMetaCache, collectionMembershipCache);
|
|
66
|
+
const eventBus = new EventBus();
|
|
67
|
+
let lastWriteReady = null;
|
|
68
|
+
eventBus.subscribe(ReactorEventTypes.JOB_WRITE_READY, (_t, event) => {
|
|
69
|
+
lastWriteReady = {
|
|
70
|
+
operations: event.operations,
|
|
71
|
+
jobMeta: event.jobMeta
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
let signatureRefusals = [];
|
|
75
|
+
eventBus.subscribe(ReactorEventTypes.SIGNATURE_REFUSED, (_t, event) => {
|
|
76
|
+
signatureRefusals.push(event);
|
|
77
|
+
});
|
|
78
|
+
const executorConfig = options.executorConfig ?? {};
|
|
79
|
+
return {
|
|
80
|
+
executor: new SimpleJobExecutor(logger, registry, operationStore, eventBus, writeCache, operationIndex, documentMetaCache, collectionMembershipCache, driveContainerTypes, executorConfig, executionScope, signer, trustPolicy),
|
|
81
|
+
registry,
|
|
82
|
+
takeLastWriteReady() {
|
|
83
|
+
const captured = lastWriteReady;
|
|
84
|
+
lastWriteReady = null;
|
|
85
|
+
return captured;
|
|
86
|
+
},
|
|
87
|
+
takeSignatureRefusals() {
|
|
88
|
+
const captured = signatureRefusals;
|
|
89
|
+
signatureRefusals = [];
|
|
90
|
+
return captured;
|
|
91
|
+
},
|
|
92
|
+
evictPurged(documentIds) {
|
|
93
|
+
for (const documentId of documentIds) {
|
|
94
|
+
writeCache.invalidate(documentId);
|
|
95
|
+
documentMetaCache.invalidate(documentId);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
6
101
|
//#region src/executor/worker/run-worker.ts
|
|
7
102
|
const POOL_SAMPLE_INTERVAL_MS = 1e3;
|
|
8
103
|
async function defaultCreateDatabase(config, workerId) {
|
|
@@ -38,7 +133,7 @@ async function defaultCreateDatabase(config, workerId) {
|
|
|
38
133
|
/**
|
|
39
134
|
* Drives the worker's message loop. Owns lifecycle of the database handle
|
|
40
135
|
* and executor stack. The default factories build a real Postgres pool and
|
|
41
|
-
* use dynamic `import()` for model/
|
|
136
|
+
* use dynamic `import()` for model/signer specs; tests inject overrides
|
|
42
137
|
* for an in-process PGlite path.
|
|
43
138
|
*/
|
|
44
139
|
function runWorker(parentPort, overrides = {}) {
|
|
@@ -51,6 +146,7 @@ function runWorker(parentPort, overrides = {}) {
|
|
|
51
146
|
let pendingPoolSamples = [];
|
|
52
147
|
let detachPoolListener = null;
|
|
53
148
|
const activeLoadFactory = overrides.loadFactory ?? defaultLoadFactory;
|
|
149
|
+
const loadModelSpec = overrides.loadFactory ? async (spec) => await activeLoadFactory(spec) : loadDocumentModelSpec;
|
|
54
150
|
function post(msg) {
|
|
55
151
|
parentPort.postMessage(msg);
|
|
56
152
|
}
|
|
@@ -146,11 +242,16 @@ function runWorker(parentPort, overrides = {}) {
|
|
|
146
242
|
return;
|
|
147
243
|
}
|
|
148
244
|
try {
|
|
245
|
+
const result = await executorStack.executor.executeJob(job);
|
|
246
|
+
const writeReady = executorStack.takeLastWriteReady();
|
|
247
|
+
const signatureRefusals = executorStack.takeSignatureRefusals();
|
|
149
248
|
post({
|
|
150
249
|
type: "result",
|
|
151
250
|
correlationId,
|
|
152
|
-
result
|
|
153
|
-
writeReady:
|
|
251
|
+
result,
|
|
252
|
+
writeReady: writeReady ?? void 0,
|
|
253
|
+
signatureRefusals: signatureRefusals.length > 0 ? signatureRefusals : void 0,
|
|
254
|
+
error: !result.success && result.error ? errorToInfo(result.error) : void 0
|
|
154
255
|
});
|
|
155
256
|
} catch (error) {
|
|
156
257
|
post({
|
|
@@ -178,7 +279,7 @@ function runWorker(parentPort, overrides = {}) {
|
|
|
178
279
|
}
|
|
179
280
|
let module;
|
|
180
281
|
try {
|
|
181
|
-
module = await
|
|
282
|
+
module = await loadModelSpec(msg.model.spec);
|
|
182
283
|
} catch (error) {
|
|
183
284
|
post({
|
|
184
285
|
type: "model-load-failed",
|
|
@@ -277,6 +378,9 @@ function runWorker(parentPort, overrides = {}) {
|
|
|
277
378
|
});
|
|
278
379
|
});
|
|
279
380
|
break;
|
|
381
|
+
case "evict-purged":
|
|
382
|
+
executorStack?.evictPurged(msg.documentIds);
|
|
383
|
+
break;
|
|
280
384
|
default: {
|
|
281
385
|
const raw = msg;
|
|
282
386
|
if (raw["type"] === "__test_throw") {
|
package/dist/entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.js","names":[],"sources":["../src/executor/worker/run-worker.ts","../src/executor/worker/entry.ts"],"sourcesContent":["import type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport { ConsoleLogger } from \"document-model\";\nimport type { Kysely } from \"kysely\";\nimport type { MessagePort } from \"node:worker_threads\";\nimport type { Database } from \"../../core/types.js\";\nimport type { Job } from \"../../queue/types.js\";\nimport {\n instrumentPgPool,\n type PoolInstrumentation,\n} from \"../../storage/pool-instrumentation.js\";\nimport {\n buildWorkerExecutor,\n defaultLoadFactory,\n type BuildWorkerExecutorOptions,\n type WorkerExecutorStack,\n} from \"./build-worker-executor.js\";\nimport { createForwardingLogger } from \"./forwarding-logger.js\";\nimport type {\n DbConfig,\n FactorySpec,\n InitMessage,\n LoadModelMessage,\n ParentMessage,\n WorkerMessage,\n} from \"./protocol.js\";\nimport { errorToInfo } from \"./sanitize.js\";\n\nconst POOL_SAMPLE_INTERVAL_MS = 1_000;\n\n/**\n * Closeable handle around the parent's Postgres pool the worker owns.\n * Decoupled so tests can substitute a PGlite-backed Kysely.\n *\n * When the worker owns a real pg.Pool, the handle exposes a\n * {@link PoolInstrumentation} so the run-loop can subscribe to acquire-wait\n * samples and forward them to the host. Tests that swap in PGlite leave\n * this undefined; pool metrics simply do not emit in that path.\n */\nexport type WorkerDatabaseHandle = {\n kysely: Kysely<Database>;\n poolInstrumentation?: PoolInstrumentation;\n shutdown(): Promise<void>;\n};\n\nexport type RunWorkerOverrides = {\n /**\n * Builds the worker's Kysely instance from the init's DbConfig. Defaults\n * to a real Postgres pool. Tests typically swap this for PGlite.\n */\n createDatabase?: (\n config: DbConfig,\n workerId: string,\n ) => Promise<WorkerDatabaseHandle>;\n /**\n * Overrides the dynamic-import factory loader used for the signature\n * verifier and document model manifest. Tests usually inject this so\n * they don't need real packages.\n */\n loadFactory?: BuildWorkerExecutorOptions[\"loadFactory\"];\n /**\n * Called after the database is created but before the executor stack\n * is built. Lets tests run reactor migrations against PGlite, since\n * the production parent runs them once against shared Postgres.\n */\n beforeBuildExecutor?: (db: Kysely<Database>) => Promise<void>;\n};\n\nasync function defaultCreateDatabase(\n config: DbConfig,\n workerId: string,\n): Promise<WorkerDatabaseHandle> {\n const { Kysely, PostgresDialect } = await import(\"kysely\");\n const pgModule = await import(\"pg\");\n const Pool = pgModule.default.Pool;\n const pool = new Pool({\n host: config.host,\n port: config.port,\n database: config.database,\n user: config.user,\n password: config.password,\n ssl: config.ssl ? { rejectUnauthorized: false } : undefined,\n application_name: config.applicationName ?? workerId,\n max: config.poolSize,\n connectionTimeoutMillis: config.connectionTimeoutMillis,\n idleTimeoutMillis: config.idleTimeoutMillis,\n });\n const poolInstrumentation = instrumentPgPool(pool, workerId);\n const kysely = new Kysely<Database>({\n dialect: new PostgresDialect({ pool }),\n });\n return {\n kysely,\n poolInstrumentation,\n async shutdown(): Promise<void> {\n try {\n await kysely.destroy();\n } catch {\n // best-effort\n }\n try {\n await pool.end();\n } catch {\n // best-effort\n }\n },\n };\n}\n\n/**\n * Drives the worker's message loop. Owns lifecycle of the database handle\n * and executor stack. The default factories build a real Postgres pool and\n * use dynamic `import()` for model/verifier specs; tests inject overrides\n * for an in-process PGlite path.\n */\nexport function runWorker(\n parentPort: MessagePort,\n overrides: RunWorkerOverrides = {},\n): void {\n let workerId = \"\";\n let initCompleted = false;\n let initConfig: InitMessage | null = null;\n let executorStack: WorkerExecutorStack | null = null;\n let database: WorkerDatabaseHandle | null = null;\n let poolSampleTimer: NodeJS.Timeout | null = null;\n let pendingPoolSamples: number[] = [];\n let detachPoolListener: (() => void) | null = null;\n const activeLoadFactory: NonNullable<\n BuildWorkerExecutorOptions[\"loadFactory\"]\n > = overrides.loadFactory ?? defaultLoadFactory;\n\n function post(msg: WorkerMessage): void {\n parentPort.postMessage(msg);\n }\n\n const logger = createForwardingLogger(post);\n\n function startPoolReporter(instrumentation: PoolInstrumentation): void {\n detachPoolListener = instrumentation.onAcquire((durationMs) => {\n pendingPoolSamples.push(durationMs);\n });\n poolSampleTimer = setInterval(() => {\n if (pendingPoolSamples.length === 0) {\n return;\n }\n const durations = pendingPoolSamples;\n pendingPoolSamples = [];\n const stats = instrumentation.getStats();\n post({\n type: \"pool-acquire-samples\",\n workerId,\n poolName: instrumentation.name,\n timestamp: Date.now(),\n durations,\n size: stats.size,\n idle: stats.idle,\n waiting: stats.waiting,\n });\n }, POOL_SAMPLE_INTERVAL_MS);\n poolSampleTimer.unref();\n }\n\n function stopPoolReporter(): void {\n if (detachPoolListener) {\n detachPoolListener();\n detachPoolListener = null;\n }\n if (poolSampleTimer) {\n clearInterval(poolSampleTimer);\n poolSampleTimer = null;\n }\n pendingPoolSamples = [];\n }\n\n process.on(\"uncaughtException\", (err: unknown) => {\n try {\n post({\n type: \"log\",\n level: \"error\",\n message: \"worker uncaughtException\",\n args: [errorToInfo(err)],\n timestamp: Date.now(),\n });\n } catch {\n // nothing left to do\n }\n throw err;\n });\n\n process.on(\"unhandledRejection\", (reason: unknown) => {\n try {\n post({\n type: \"log\",\n level: \"error\",\n message: \"worker unhandledRejection\",\n args: [errorToInfo(reason)],\n timestamp: Date.now(),\n });\n } catch {\n // nothing left to do\n }\n });\n\n async function handleInit(msg: InitMessage): Promise<void> {\n workerId = msg.workerId;\n initConfig = msg;\n const createDb = overrides.createDatabase ?? defaultCreateDatabase;\n database = await createDb(msg.db, msg.workerId);\n if (overrides.beforeBuildExecutor) {\n await overrides.beforeBuildExecutor(database.kysely);\n }\n executorStack = await buildWorkerExecutor({\n init: msg,\n database: database.kysely,\n logger: new ConsoleLogger([`reactor-worker:${msg.workerId}`]),\n executorConfig: msg.executorConfig,\n loadFactory: activeLoadFactory,\n });\n if (database.poolInstrumentation) {\n startPoolReporter(database.poolInstrumentation);\n }\n initCompleted = true;\n logger.info(\"worker initialized: @workerId\", msg.workerId);\n post({\n type: \"ready\",\n correlationId: msg.correlationId,\n workerId: msg.workerId,\n });\n }\n\n async function handleExecute(correlationId: string, job: Job): Promise<void> {\n if (!executorStack) {\n post({\n type: \"result\",\n correlationId,\n result: { job, success: false },\n error: errorToInfo(new Error(\"execute received before init\")),\n });\n return;\n }\n try {\n const result = await executorStack.executor.executeJob(job);\n const writeReady = executorStack.takeLastWriteReady();\n post({\n type: \"result\",\n correlationId,\n result,\n writeReady: writeReady ?? undefined,\n });\n } catch (error) {\n post({\n type: \"result\",\n correlationId,\n result: { job, success: false },\n error: errorToInfo(error),\n });\n }\n }\n\n async function handleLoadModel(msg: LoadModelMessage): Promise<void> {\n const stack = executorStack;\n if (!stack) {\n post({\n type: \"model-load-failed\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n error: errorToInfo(new Error(\"load-model received before init\")),\n });\n return;\n }\n let module: DocumentModelModule;\n try {\n module = (await activeLoadFactory(msg.model.spec)) as DocumentModelModule;\n } catch (error) {\n post({\n type: \"model-load-failed\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n error: errorToInfo(error),\n });\n return;\n }\n const [result] = stack.registry.registerModules(module);\n if (result.status === \"error\") {\n post({\n type: \"model-load-failed\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n error: errorToInfo(result.error),\n });\n return;\n }\n post({\n type: \"model-loaded\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n });\n }\n\n async function shutdownDatabase(): Promise<void> {\n stopPoolReporter();\n if (database) {\n await database.shutdown();\n }\n }\n\n function handleParentMessage(msg: ParentMessage): void {\n switch (msg.type) {\n case \"init\": {\n handleInit(msg).catch((err: unknown) => {\n post({\n type: \"log\",\n level: \"error\",\n message: \"worker init failed\",\n args: [errorToInfo(err)],\n timestamp: Date.now(),\n });\n });\n break;\n }\n\n case \"execute\": {\n if (!initCompleted) {\n logger.warn(\"received execute before init\");\n post({\n type: \"result\",\n correlationId: msg.correlationId,\n result: { job: msg.job, success: false },\n error: errorToInfo(new Error(\"execute received before init\")),\n });\n break;\n }\n handleExecute(msg.correlationId, msg.job).catch((err: unknown) => {\n post({\n type: \"result\",\n correlationId: msg.correlationId,\n result: { job: msg.job, success: false },\n error: errorToInfo(err),\n });\n });\n break;\n }\n\n case \"shutdown\": {\n logger.info(\"worker shutting down: @workerId\", workerId);\n void shutdownDatabase().finally(() => {\n post({\n type: \"log\",\n level: \"info\",\n message: \"worker shutdown\",\n args: [],\n timestamp: Date.now(),\n });\n process.exit(0);\n });\n break;\n }\n\n case \"abort\": {\n logger.warn(\n \"abort received (no-op stub): @correlationId\",\n msg.correlationId,\n );\n break;\n }\n\n case \"load-model\": {\n handleLoadModel(msg).catch((err: unknown) => {\n post({\n type: \"model-load-failed\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n error: errorToInfo(err),\n });\n });\n break;\n }\n\n default: {\n const raw = msg as Record<string, unknown>;\n if (raw[\"type\"] === \"__test_throw\") {\n const rawReason = raw[\"reason\"];\n const reason =\n typeof rawReason === \"string\"\n ? rawReason\n : \"synthetic uncaughtException\";\n setTimeout(() => {\n throw new Error(reason);\n }, 0);\n return;\n }\n const _exhaustive: never = msg;\n void _exhaustive;\n break;\n }\n }\n }\n\n parentPort.on(\"message\", handleParentMessage);\n\n // Test-only exports surfaced on a side-channel for unit tests that drive\n // the message loop directly without a real worker_threads parent.\n const harness = {\n handleParentMessage,\n get initCompleted(): boolean {\n return initCompleted;\n },\n get initConfig(): InitMessage | null {\n return initConfig;\n },\n get workerId(): string {\n return workerId;\n },\n };\n (\n parentPort as unknown as { __reactorWorkerHarness?: unknown }\n ).__reactorWorkerHarness = harness;\n}\n\nexport type FactorySpecForTesting = FactorySpec;\n","import { isMainThread, parentPort } from \"node:worker_threads\";\nimport { runWorker } from \"./run-worker.js\";\n\nif (isMainThread || parentPort === null) {\n throw new Error(\"entry.ts must be run as a worker thread\");\n}\n\nrunWorker(parentPort);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"entry.js","names":[],"sources":["../src/executor/worker/build-worker-executor.ts","../src/executor/worker/run-worker.ts","../src/executor/worker/entry.ts"],"sourcesContent":["import type {\n DocumentModelModule,\n ISigner,\n OperationWithContext,\n} from \"@powerhousedao/shared/document-model\";\nimport type { ILogger } from \"document-model\";\nimport type { Kysely } from \"kysely\";\nimport { CollectionMembershipCache } from \"../../cache/collection-membership-cache.js\";\nimport { DocumentMetaCache } from \"../../cache/document-meta-cache.js\";\nimport { KyselyOperationIndex } from \"../../cache/kysely-operation-index.js\";\nimport { KyselyWriteCache } from \"../../cache/kysely-write-cache.js\";\nimport type { WriteCacheConfig } from \"../../cache/write-cache-types.js\";\nimport { DEFAULT_DRIVE_CONTAINER_TYPES } from \"../../core/drive-container-types.js\";\nimport type { Database } from \"../../core/types.js\";\nimport { EventBus } from \"../../events/event-bus.js\";\nimport {\n ReactorEventTypes,\n type JobWriteReadyEvent,\n type SignatureRefusedEvent,\n} from \"../../events/types.js\";\nimport { DocumentModelRegistry } from \"../../registry/implementation.js\";\nimport type { JobMeta } from \"../../shared/types.js\";\nimport { KyselyKeyframeStore } from \"../../storage/kysely/keyframe-store.js\";\nimport { KyselyOperationStore } from \"../../storage/kysely/store.js\";\nimport type { Database as StorageDatabase } from \"../../storage/kysely/types.js\";\nimport { REACTOR_SCHEMA } from \"../../storage/migrations/migrator.js\";\nimport { KyselyExecutionScope } from \"../execution-scope.js\";\nimport { SimpleJobExecutor } from \"../simple-job-executor.js\";\nimport type { SignatureTrustPolicy } from \"../../signer/types.js\";\nimport type { JobExecutorConfig } from \"../types.js\";\nimport type {\n FactorySpec,\n InitMessage,\n ModelManifestEntry,\n} from \"./protocol.js\";\nimport { defaultLoadFactory } from \"./load-spec.js\";\n\n/**\n * In-worker capture of the JOB_WRITE_READY event emitted by the executor.\n * The worker forwards `operations` and `jobMeta` back to the parent; the\n * parent re-enriches `collectionMemberships` at emit time.\n */\nexport type WorkerWriteReadyCapture = {\n operations: OperationWithContext[];\n jobMeta: JobMeta;\n};\n\nexport type WorkerExecutorStack = {\n executor: SimpleJobExecutor;\n registry: DocumentModelRegistry;\n /**\n * Synchronously pops the most-recent JOB_WRITE_READY captured on this\n * worker's local event bus and clears it. Returns null if the executor\n * did not produce one for this job.\n */\n takeLastWriteReady(): WorkerWriteReadyCapture | null;\n /** Drains the refusals this worker's executor emitted since the last call. */\n takeSignatureRefusals(): SignatureRefusedEvent[];\n /** Drops purged ids from this worker's write and meta caches. */\n evictPurged(documentIds: string[]): void;\n};\n\nexport type BuildWorkerExecutorOptions = {\n init: InitMessage;\n database: Kysely<Database>;\n logger: ILogger;\n executorConfig?: JobExecutorConfig;\n driveContainerTypes?: ReadonlySet<string>;\n /**\n * Override the module loader used to materialize factory specs. Tests\n * can inject a deterministic resolver instead of touching the real\n * Node module loader.\n */\n loadFactory?: (spec: FactorySpec) => Promise<unknown>;\n};\n\nasync function loadModelManifest(\n entries: ModelManifestEntry[],\n loadFactory: (spec: FactorySpec) => Promise<unknown>,\n registry: DocumentModelRegistry,\n logger: ILogger,\n): Promise<void> {\n for (const entry of entries) {\n let module: DocumentModelModule;\n try {\n module = (await loadFactory(entry.spec)) as DocumentModelModule;\n } catch (error) {\n logger.error(\n \"worker failed to load document model: @entry @error\",\n entry,\n error,\n );\n throw error;\n }\n const [result] = registry.registerModules(module);\n if (result.status === \"error\") {\n logger.error(\n \"worker failed to register document model: @entry @error\",\n entry,\n result.error,\n );\n throw result.error;\n }\n }\n}\n\n/**\n * Assembles the in-worker storage stack plus a {@link SimpleJobExecutor}\n * bound to a pre-built Kysely instance. The parent owns the wire protocol\n * and routing; the worker owns everything below `SimpleJobExecutor`.\n *\n * The local event bus exists only to satisfy the executor's contract: its\n * JOB_WRITE_READY emissions are captured here and shipped to the parent\n * via {@link WorkerExecutorStack.takeLastWriteReady}.\n */\nexport async function buildWorkerExecutor(\n options: BuildWorkerExecutorOptions,\n): Promise<WorkerExecutorStack> {\n const { init, database: baseDatabase, logger } = options;\n const driveContainerTypes =\n options.driveContainerTypes ?? DEFAULT_DRIVE_CONTAINER_TYPES;\n const loadFactory = options.loadFactory ?? defaultLoadFactory;\n\n const registry = new DocumentModelRegistry();\n await loadModelManifest(init.models, loadFactory, registry, logger);\n\n let signer: ISigner | undefined;\n if (init.signer) {\n try {\n signer = (await loadFactory(init.signer)) as ISigner;\n } catch (error) {\n logger.error(\n \"worker failed to load signer: @spec @error\",\n init.signer.module,\n error,\n );\n throw error;\n }\n }\n\n let trustPolicy: SignatureTrustPolicy | undefined;\n if (init.trustPolicy) {\n try {\n trustPolicy = (await loadFactory(\n init.trustPolicy,\n )) as SignatureTrustPolicy;\n } catch (error) {\n logger.error(\n \"worker failed to load trust policy: @spec @error\",\n init.trustPolicy.module,\n error,\n );\n throw error;\n }\n }\n\n const database = baseDatabase.withSchema(REACTOR_SCHEMA);\n const operationStore = new KyselyOperationStore(\n database as unknown as Kysely<StorageDatabase>,\n );\n const keyframeStore = new KyselyKeyframeStore(\n database as unknown as Kysely<StorageDatabase>,\n );\n\n const cacheConfig: WriteCacheConfig = {\n maxDocuments: 100,\n ringBufferSize: 10,\n keyframeInterval: 10,\n };\n const writeCache = new KyselyWriteCache(\n keyframeStore,\n operationStore,\n registry,\n cacheConfig,\n );\n await writeCache.startup();\n\n const operationIndex = new KyselyOperationIndex(\n database as unknown as Kysely<StorageDatabase>,\n );\n\n const documentMetaCache = new DocumentMetaCache(operationStore, {\n maxDocuments: 1000,\n });\n await documentMetaCache.startup();\n\n const collectionMembershipCache = new CollectionMembershipCache(\n operationIndex,\n );\n\n const executionScope = new KyselyExecutionScope(\n database as unknown as Kysely<StorageDatabase>,\n operationStore,\n operationIndex,\n keyframeStore,\n writeCache,\n documentMetaCache,\n collectionMembershipCache,\n );\n\n const eventBus = new EventBus();\n let lastWriteReady: WorkerWriteReadyCapture | null = null;\n eventBus.subscribe(\n ReactorEventTypes.JOB_WRITE_READY,\n (_t: number, event: JobWriteReadyEvent) => {\n lastWriteReady = {\n operations: event.operations,\n jobMeta: event.jobMeta,\n };\n },\n );\n\n let signatureRefusals: SignatureRefusedEvent[] = [];\n eventBus.subscribe(\n ReactorEventTypes.SIGNATURE_REFUSED,\n (_t: number, event: SignatureRefusedEvent) => {\n signatureRefusals.push(event);\n },\n );\n\n const executorConfig = options.executorConfig ?? {};\n const executor = new SimpleJobExecutor(\n logger,\n registry,\n operationStore,\n eventBus,\n writeCache,\n operationIndex,\n documentMetaCache,\n collectionMembershipCache,\n driveContainerTypes,\n executorConfig,\n executionScope,\n signer,\n trustPolicy,\n );\n\n return {\n executor,\n registry,\n takeLastWriteReady(): WorkerWriteReadyCapture | null {\n const captured = lastWriteReady;\n lastWriteReady = null;\n return captured;\n },\n takeSignatureRefusals(): SignatureRefusedEvent[] {\n const captured = signatureRefusals;\n signatureRefusals = [];\n return captured;\n },\n evictPurged(documentIds: string[]): void {\n for (const documentId of documentIds) {\n writeCache.invalidate(documentId);\n documentMetaCache.invalidate(documentId);\n }\n },\n };\n}\n","import type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport { ConsoleLogger } from \"document-model\";\nimport type { Kysely } from \"kysely\";\nimport type { MessagePort } from \"node:worker_threads\";\nimport type { Database } from \"../../core/types.js\";\nimport type { Job } from \"../../queue/types.js\";\nimport {\n instrumentPgPool,\n type PoolInstrumentation,\n} from \"../../storage/pool-instrumentation.js\";\nimport {\n buildWorkerExecutor,\n type BuildWorkerExecutorOptions,\n type WorkerExecutorStack,\n} from \"./build-worker-executor.js\";\nimport { createForwardingLogger } from \"./forwarding-logger.js\";\nimport { defaultLoadFactory, loadDocumentModelSpec } from \"./load-spec.js\";\nimport type {\n DbConfig,\n DocumentModelSpec,\n FactorySpec,\n InitMessage,\n LoadModelMessage,\n ParentMessage,\n WorkerMessage,\n} from \"./protocol.js\";\nimport { errorToInfo } from \"./sanitize.js\";\n\nconst POOL_SAMPLE_INTERVAL_MS = 1_000;\n\n/**\n * Closeable handle around the parent's Postgres pool the worker owns.\n * Decoupled so tests can substitute a PGlite-backed Kysely.\n *\n * When the worker owns a real pg.Pool, the handle exposes a\n * {@link PoolInstrumentation} so the run-loop can subscribe to acquire-wait\n * samples and forward them to the host. Tests that swap in PGlite leave\n * this undefined; pool metrics simply do not emit in that path.\n */\nexport type WorkerDatabaseHandle = {\n kysely: Kysely<Database>;\n poolInstrumentation?: PoolInstrumentation;\n shutdown(): Promise<void>;\n};\n\nexport type RunWorkerOverrides = {\n /**\n * Builds the worker's Kysely instance from the init's DbConfig. Defaults\n * to a real Postgres pool. Tests typically swap this for PGlite.\n */\n createDatabase?: (\n config: DbConfig,\n workerId: string,\n ) => Promise<WorkerDatabaseHandle>;\n /**\n * Overrides the dynamic-import factory loader used for the signer and\n * document model manifest. Tests usually inject this so\n * they don't need real packages.\n */\n loadFactory?: BuildWorkerExecutorOptions[\"loadFactory\"];\n /**\n * Called after the database is created but before the executor stack\n * is built. Lets tests run reactor migrations against PGlite, since\n * the production parent runs them once against shared Postgres.\n */\n beforeBuildExecutor?: (db: Kysely<Database>) => Promise<void>;\n};\n\nasync function defaultCreateDatabase(\n config: DbConfig,\n workerId: string,\n): Promise<WorkerDatabaseHandle> {\n const { Kysely, PostgresDialect } = await import(\"kysely\");\n const pgModule = await import(\"pg\");\n const Pool = pgModule.default.Pool;\n const pool = new Pool({\n host: config.host,\n port: config.port,\n database: config.database,\n user: config.user,\n password: config.password,\n ssl: config.ssl ? { rejectUnauthorized: false } : undefined,\n application_name: config.applicationName ?? workerId,\n max: config.poolSize,\n connectionTimeoutMillis: config.connectionTimeoutMillis,\n idleTimeoutMillis: config.idleTimeoutMillis,\n });\n const poolInstrumentation = instrumentPgPool(pool, workerId);\n const kysely = new Kysely<Database>({\n dialect: new PostgresDialect({ pool }),\n });\n return {\n kysely,\n poolInstrumentation,\n async shutdown(): Promise<void> {\n try {\n await kysely.destroy();\n } catch {\n // best-effort\n }\n try {\n await pool.end();\n } catch {\n // best-effort\n }\n },\n };\n}\n\n/**\n * Drives the worker's message loop. Owns lifecycle of the database handle\n * and executor stack. The default factories build a real Postgres pool and\n * use dynamic `import()` for model/signer specs; tests inject overrides\n * for an in-process PGlite path.\n */\nexport function runWorker(\n parentPort: MessagePort,\n overrides: RunWorkerOverrides = {},\n): void {\n let workerId = \"\";\n let initCompleted = false;\n let initConfig: InitMessage | null = null;\n let executorStack: WorkerExecutorStack | null = null;\n let database: WorkerDatabaseHandle | null = null;\n let poolSampleTimer: NodeJS.Timeout | null = null;\n let pendingPoolSamples: number[] = [];\n let detachPoolListener: (() => void) | null = null;\n const activeLoadFactory: NonNullable<\n BuildWorkerExecutorOptions[\"loadFactory\"]\n > = overrides.loadFactory ?? defaultLoadFactory;\n const loadModelSpec = overrides.loadFactory\n ? async (spec: DocumentModelSpec) =>\n (await activeLoadFactory(spec)) as DocumentModelModule\n : loadDocumentModelSpec;\n\n function post(msg: WorkerMessage): void {\n parentPort.postMessage(msg);\n }\n\n const logger = createForwardingLogger(post);\n\n function startPoolReporter(instrumentation: PoolInstrumentation): void {\n detachPoolListener = instrumentation.onAcquire((durationMs) => {\n pendingPoolSamples.push(durationMs);\n });\n poolSampleTimer = setInterval(() => {\n if (pendingPoolSamples.length === 0) {\n return;\n }\n const durations = pendingPoolSamples;\n pendingPoolSamples = [];\n const stats = instrumentation.getStats();\n post({\n type: \"pool-acquire-samples\",\n workerId,\n poolName: instrumentation.name,\n timestamp: Date.now(),\n durations,\n size: stats.size,\n idle: stats.idle,\n waiting: stats.waiting,\n });\n }, POOL_SAMPLE_INTERVAL_MS);\n poolSampleTimer.unref();\n }\n\n function stopPoolReporter(): void {\n if (detachPoolListener) {\n detachPoolListener();\n detachPoolListener = null;\n }\n if (poolSampleTimer) {\n clearInterval(poolSampleTimer);\n poolSampleTimer = null;\n }\n pendingPoolSamples = [];\n }\n\n process.on(\"uncaughtException\", (err: unknown) => {\n try {\n post({\n type: \"log\",\n level: \"error\",\n message: \"worker uncaughtException\",\n args: [errorToInfo(err)],\n timestamp: Date.now(),\n });\n } catch {\n // nothing left to do\n }\n throw err;\n });\n\n process.on(\"unhandledRejection\", (reason: unknown) => {\n try {\n post({\n type: \"log\",\n level: \"error\",\n message: \"worker unhandledRejection\",\n args: [errorToInfo(reason)],\n timestamp: Date.now(),\n });\n } catch {\n // nothing left to do\n }\n });\n\n async function handleInit(msg: InitMessage): Promise<void> {\n workerId = msg.workerId;\n initConfig = msg;\n const createDb = overrides.createDatabase ?? defaultCreateDatabase;\n database = await createDb(msg.db, msg.workerId);\n if (overrides.beforeBuildExecutor) {\n await overrides.beforeBuildExecutor(database.kysely);\n }\n executorStack = await buildWorkerExecutor({\n init: msg,\n database: database.kysely,\n logger: new ConsoleLogger([`reactor-worker:${msg.workerId}`]),\n executorConfig: msg.executorConfig,\n loadFactory: activeLoadFactory,\n });\n if (database.poolInstrumentation) {\n startPoolReporter(database.poolInstrumentation);\n }\n initCompleted = true;\n logger.info(\"worker initialized: @workerId\", msg.workerId);\n post({\n type: \"ready\",\n correlationId: msg.correlationId,\n workerId: msg.workerId,\n });\n }\n\n async function handleExecute(correlationId: string, job: Job): Promise<void> {\n if (!executorStack) {\n post({\n type: \"result\",\n correlationId,\n result: { job, success: false },\n error: errorToInfo(new Error(\"execute received before init\")),\n });\n return;\n }\n try {\n const result = await executorStack.executor.executeJob(job);\n const writeReady = executorStack.takeLastWriteReady();\n const signatureRefusals = executorStack.takeSignatureRefusals();\n post({\n type: \"result\",\n correlationId,\n result,\n writeReady: writeReady ?? undefined,\n signatureRefusals:\n signatureRefusals.length > 0 ? signatureRefusals : undefined,\n // Structured clone drops a custom error name; the ErrorInfo keeps it.\n error:\n !result.success && result.error\n ? errorToInfo(result.error)\n : undefined,\n });\n } catch (error) {\n post({\n type: \"result\",\n correlationId,\n result: { job, success: false },\n error: errorToInfo(error),\n });\n }\n }\n\n async function handleLoadModel(msg: LoadModelMessage): Promise<void> {\n const stack = executorStack;\n if (!stack) {\n post({\n type: \"model-load-failed\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n error: errorToInfo(new Error(\"load-model received before init\")),\n });\n return;\n }\n let module: DocumentModelModule;\n try {\n module = await loadModelSpec(msg.model.spec);\n } catch (error) {\n post({\n type: \"model-load-failed\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n error: errorToInfo(error),\n });\n return;\n }\n const [result] = stack.registry.registerModules(module);\n if (result.status === \"error\") {\n post({\n type: \"model-load-failed\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n error: errorToInfo(result.error),\n });\n return;\n }\n post({\n type: \"model-loaded\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n });\n }\n\n async function shutdownDatabase(): Promise<void> {\n stopPoolReporter();\n if (database) {\n await database.shutdown();\n }\n }\n\n function handleParentMessage(msg: ParentMessage): void {\n switch (msg.type) {\n case \"init\": {\n handleInit(msg).catch((err: unknown) => {\n post({\n type: \"log\",\n level: \"error\",\n message: \"worker init failed\",\n args: [errorToInfo(err)],\n timestamp: Date.now(),\n });\n });\n break;\n }\n\n case \"execute\": {\n if (!initCompleted) {\n logger.warn(\"received execute before init\");\n post({\n type: \"result\",\n correlationId: msg.correlationId,\n result: { job: msg.job, success: false },\n error: errorToInfo(new Error(\"execute received before init\")),\n });\n break;\n }\n handleExecute(msg.correlationId, msg.job).catch((err: unknown) => {\n post({\n type: \"result\",\n correlationId: msg.correlationId,\n result: { job: msg.job, success: false },\n error: errorToInfo(err),\n });\n });\n break;\n }\n\n case \"shutdown\": {\n logger.info(\"worker shutting down: @workerId\", workerId);\n void shutdownDatabase().finally(() => {\n post({\n type: \"log\",\n level: \"info\",\n message: \"worker shutdown\",\n args: [],\n timestamp: Date.now(),\n });\n process.exit(0);\n });\n break;\n }\n\n case \"abort\": {\n logger.warn(\n \"abort received (no-op stub): @correlationId\",\n msg.correlationId,\n );\n break;\n }\n\n case \"load-model\": {\n handleLoadModel(msg).catch((err: unknown) => {\n post({\n type: \"model-load-failed\",\n correlationId: msg.correlationId,\n documentType: msg.model.documentType,\n version: msg.model.version,\n error: errorToInfo(err),\n });\n });\n break;\n }\n\n case \"evict-purged\": {\n executorStack?.evictPurged(msg.documentIds);\n break;\n }\n\n default: {\n const raw = msg as Record<string, unknown>;\n if (raw[\"type\"] === \"__test_throw\") {\n const rawReason = raw[\"reason\"];\n const reason =\n typeof rawReason === \"string\"\n ? rawReason\n : \"synthetic uncaughtException\";\n setTimeout(() => {\n throw new Error(reason);\n }, 0);\n return;\n }\n const _exhaustive: never = msg;\n void _exhaustive;\n break;\n }\n }\n }\n\n parentPort.on(\"message\", handleParentMessage);\n\n // Test-only exports surfaced on a side-channel for unit tests that drive\n // the message loop directly without a real worker_threads parent.\n const harness = {\n handleParentMessage,\n get initCompleted(): boolean {\n return initCompleted;\n },\n get initConfig(): InitMessage | null {\n return initConfig;\n },\n get workerId(): string {\n return workerId;\n },\n };\n (\n parentPort as unknown as { __reactorWorkerHarness?: unknown }\n ).__reactorWorkerHarness = harness;\n}\n\nexport type FactorySpecForTesting = FactorySpec;\n","import { isMainThread, parentPort } from \"node:worker_threads\";\nimport { runWorker } from \"./run-worker.js\";\n\nif (isMainThread || parentPort === null) {\n throw new Error(\"entry.ts must be run as a worker thread\");\n}\n\nrunWorker(parentPort);\n"],"mappings":"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"}
|
|
@@ -13,6 +13,8 @@ var WorkerBusyError = class extends Error {
|
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
var WorkerExitedError = class extends Error {
|
|
16
|
+
exitCode;
|
|
17
|
+
lastCorrelationId;
|
|
16
18
|
name = "WorkerExitedError";
|
|
17
19
|
constructor(workerId, exitCode, lastCorrelationId) {
|
|
18
20
|
super(`worker ${workerId} exited with code ${exitCode}` + (lastCorrelationId ? ` while handling correlationId ${lastCorrelationId}` : ""));
|
|
@@ -21,6 +23,8 @@ var WorkerExitedError = class extends Error {
|
|
|
21
23
|
}
|
|
22
24
|
};
|
|
23
25
|
var WorkerAbortTimeoutError = class extends Error {
|
|
26
|
+
correlationId;
|
|
27
|
+
graceMs;
|
|
24
28
|
name = "WorkerAbortTimeoutError";
|
|
25
29
|
constructor(workerId, correlationId, graceMs) {
|
|
26
30
|
super(`worker ${workerId} did not acknowledge abort for ${correlationId} within ${graceMs}ms; terminating`);
|
|
@@ -29,6 +33,7 @@ var WorkerAbortTimeoutError = class extends Error {
|
|
|
29
33
|
}
|
|
30
34
|
};
|
|
31
35
|
var WorkerInitFailedError = class extends Error {
|
|
36
|
+
reason;
|
|
32
37
|
name = "WorkerInitFailedError";
|
|
33
38
|
constructor(workerId, reason, options) {
|
|
34
39
|
super(`worker ${workerId} failed to initialize: ${reason}`, options);
|
|
@@ -36,6 +41,8 @@ var WorkerInitFailedError = class extends Error {
|
|
|
36
41
|
}
|
|
37
42
|
};
|
|
38
43
|
var WorkerLoadModelFailedError = class extends Error {
|
|
44
|
+
documentType;
|
|
45
|
+
version;
|
|
39
46
|
name = "WorkerLoadModelFailedError";
|
|
40
47
|
constructor(workerId, documentType, version, reason, options) {
|
|
41
48
|
super(`worker ${workerId} failed to load model ${documentType}@${version}: ${reason}`, options);
|
|
@@ -44,6 +51,7 @@ var WorkerLoadModelFailedError = class extends Error {
|
|
|
44
51
|
}
|
|
45
52
|
};
|
|
46
53
|
var WorkerShutdownTimeoutError = class extends Error {
|
|
54
|
+
graceMs;
|
|
47
55
|
name = "WorkerShutdownTimeoutError";
|
|
48
56
|
constructor(workerId, graceMs) {
|
|
49
57
|
super(`worker ${workerId} did not drain within ${graceMs}ms; force-terminating`);
|
|
@@ -53,4 +61,4 @@ var WorkerShutdownTimeoutError = class extends Error {
|
|
|
53
61
|
//#endregion
|
|
54
62
|
export { WorkerLoadModelFailedError as a, WorkerInitFailedError as i, WorkerBusyError as n, WorkerShutdownTimeoutError as o, WorkerExitedError as r, WorkerAbortTimeoutError as t };
|
|
55
63
|
|
|
56
|
-
//# sourceMappingURL=errors-
|
|
64
|
+
//# sourceMappingURL=errors-BM_ULVWd.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors-
|
|
1
|
+
{"version":3,"file":"errors-BM_ULVWd.js","names":[],"sources":["../src/executor/worker/errors.ts"],"sourcesContent":["/**\n * Errors emitted by {@link WorkerHandle} at the IPC / transport boundary.\n *\n * These are distinct from per-job failures (which surface as\n * `JobResult.success === false`). The manager branches on `name` to decide\n * between retrying, replacing the worker, or surfacing the failure.\n */\n\nexport class WorkerBusyError extends Error {\n readonly name = \"WorkerBusyError\";\n constructor(workerId: string, jobId: string) {\n super(\n `worker ${workerId} is busy; cannot dispatch job ${jobId} while another job is in flight`,\n );\n }\n}\n\nexport class WorkerExitedError extends Error {\n readonly name = \"WorkerExitedError\";\n constructor(\n workerId: string,\n readonly exitCode: number,\n readonly lastCorrelationId: string | null,\n ) {\n super(\n `worker ${workerId} exited with code ${exitCode}` +\n (lastCorrelationId\n ? ` while handling correlationId ${lastCorrelationId}`\n : \"\"),\n );\n }\n}\n\nexport class WorkerAbortTimeoutError extends Error {\n readonly name = \"WorkerAbortTimeoutError\";\n constructor(\n workerId: string,\n readonly correlationId: string,\n readonly graceMs: number,\n ) {\n super(\n `worker ${workerId} did not acknowledge abort for ${correlationId} within ${graceMs}ms; terminating`,\n );\n }\n}\n\nexport class WorkerInitFailedError extends Error {\n readonly name = \"WorkerInitFailedError\";\n constructor(\n workerId: string,\n readonly reason: string,\n options?: { cause?: unknown },\n ) {\n super(`worker ${workerId} failed to initialize: ${reason}`, options);\n }\n}\n\nexport class WorkerLoadModelFailedError extends Error {\n readonly name = \"WorkerLoadModelFailedError\";\n constructor(\n workerId: string,\n readonly documentType: string,\n readonly version: string,\n reason: string,\n options?: { cause?: unknown },\n ) {\n super(\n `worker ${workerId} failed to load model ${documentType}@${version}: ${reason}`,\n options,\n );\n }\n}\n\nexport class WorkerShutdownTimeoutError extends Error {\n readonly name = \"WorkerShutdownTimeoutError\";\n constructor(\n workerId: string,\n readonly graceMs: number,\n ) {\n super(\n `worker ${workerId} did not drain within ${graceMs}ms; force-terminating`,\n );\n }\n}\n"],"mappings":";;;;;;;;AAQA,IAAa,kBAAb,cAAqC,MAAM;CACzC,OAAgB;CAChB,YAAY,UAAkB,OAAe;EAC3C,MACE,UAAU,SAAS,gCAAgC,MAAM,gCAC3D;CACF;AACF;AAEA,IAAa,oBAAb,cAAuC,MAAM;CAIhC;CACA;CAJX,OAAgB;CAChB,YACE,UACA,UACA,mBACA;EACA,MACE,UAAU,SAAS,oBAAoB,cACpC,oBACG,iCAAiC,sBACjC,GACR;EARS,KAAA,WAAA;EACA,KAAA,oBAAA;CAQX;AACF;AAEA,IAAa,0BAAb,cAA6C,MAAM;CAItC;CACA;CAJX,OAAgB;CAChB,YACE,UACA,eACA,SACA;EACA,MACE,UAAU,SAAS,iCAAiC,cAAc,UAAU,QAAQ,gBACtF;EALS,KAAA,gBAAA;EACA,KAAA,UAAA;CAKX;AACF;AAEA,IAAa,wBAAb,cAA2C,MAAM;CAIpC;CAHX,OAAgB;CAChB,YACE,UACA,QACA,SACA;EACA,MAAM,UAAU,SAAS,yBAAyB,UAAU,OAAO;EAH1D,KAAA,SAAA;CAIX;AACF;AAEA,IAAa,6BAAb,cAAgD,MAAM;CAIzC;CACA;CAJX,OAAgB;CAChB,YACE,UACA,cACA,SACA,QACA,SACA;EACA,MACE,UAAU,SAAS,wBAAwB,aAAa,GAAG,QAAQ,IAAI,UACvE,OACF;EARS,KAAA,eAAA;EACA,KAAA,UAAA;CAQX;AACF;AAEA,IAAa,6BAAb,cAAgD,MAAM;CAIzC;CAHX,OAAgB;CAChB,YACE,UACA,SACA;EACA,MACE,UAAU,SAAS,wBAAwB,QAAQ,sBACrD;EAJS,KAAA,UAAA;CAKX;AACF"}
|