@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-
|
|
1
|
+
{"version":3,"file":"transport-B3G50KVd.js","names":[],"sources":["../src/projection/transport.ts"],"sourcesContent":["import { Worker, type WorkerOptions } from \"node:worker_threads\";\nimport type {\n ProjectionParentMessage,\n ProjectionWorkerMessage,\n} from \"./protocol.js\";\n\nexport type ProjectionTransportEventMap = {\n message: ProjectionWorkerMessage;\n error: Error;\n exit: number;\n};\n\nexport type ProjectionTransportEvent = keyof ProjectionTransportEventMap;\n\nexport type ProjectionTransportListener<E extends ProjectionTransportEvent> = (\n payload: ProjectionTransportEventMap[E],\n) => void;\n\n/**\n * Minimal subset of `worker_threads.Worker` the {@link ProjectionShardManager}\n * relies on. The host writes against this interface so tests can swap in\n * a fake transport without spawning real worker threads.\n */\nexport interface IProjectionTransport {\n postMessage(message: ProjectionParentMessage): void;\n on<E extends ProjectionTransportEvent>(\n event: E,\n listener: ProjectionTransportListener<E>,\n ): void;\n off<E extends ProjectionTransportEvent>(\n event: E,\n listener: ProjectionTransportListener<E>,\n ): void;\n terminate(): Promise<number>;\n}\n\nexport function createProjectionThreadTransport(\n scriptPath: string | URL,\n options?: WorkerOptions,\n): IProjectionTransport {\n const worker = new Worker(scriptPath, options);\n return {\n postMessage(message) {\n worker.postMessage(message);\n },\n on(event, listener) {\n worker.on(event, listener as (...args: unknown[]) => void);\n },\n off(event, listener) {\n worker.off(event, listener as (...args: unknown[]) => void);\n },\n async terminate() {\n return await worker.terminate();\n },\n };\n}\n"],"mappings":";;AAoCA,SAAgB,gCACd,YACA,SACsB;CACtB,MAAM,SAAS,IAAI,OAAO,YAAY,OAAO;CAC7C,OAAO;EACL,YAAY,SAAS;GACnB,OAAO,YAAY,OAAO;EAC5B;EACA,GAAG,OAAO,UAAU;GAClB,OAAO,GAAG,OAAO,QAAwC;EAC3D;EACA,IAAI,OAAO,UAAU;GACnB,OAAO,IAAI,OAAO,QAAwC;EAC5D;EACA,MAAM,YAAY;GAChB,OAAO,MAAM,OAAO,UAAU;EAChC;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-
|
|
1
|
+
{"version":3,"file":"transport-CZDHzfvy.js","names":[],"sources":["../src/executor/worker/transport.ts"],"sourcesContent":["/**\n * Transport-agnostic surface that {@link WorkerHandle} consumes.\n *\n * The handle is written against this interface — not a `worker_threads.Worker`\n * directly — so unit tests can swap in a fake transport and future cards can\n * add a `child_process` adapter without touching the handle.\n */\n\nimport { Worker, type WorkerOptions } from \"node:worker_threads\";\nimport type { ParentMessage, WorkerMessage } from \"./protocol.js\";\n\nexport type WorkerTransportEventMap = {\n message: WorkerMessage;\n error: Error;\n exit: number;\n};\n\nexport type WorkerTransportEvent = keyof WorkerTransportEventMap;\n\nexport type WorkerTransportListener<E extends WorkerTransportEvent> = (\n payload: WorkerTransportEventMap[E],\n) => void;\n\n/**\n * Minimal subset of `worker_threads.Worker` that {@link WorkerHandle} relies\n * on. Implementations must guarantee that `postMessage` payloads are\n * structured-cloned across the boundary.\n */\nexport interface IWorkerTransport {\n postMessage(message: ParentMessage): void;\n on<E extends WorkerTransportEvent>(\n event: E,\n listener: WorkerTransportListener<E>,\n ): void;\n off<E extends WorkerTransportEvent>(\n event: E,\n listener: WorkerTransportListener<E>,\n ): void;\n terminate(): Promise<number>;\n}\n\n/**\n * Wraps a `node:worker_threads` Worker so it satisfies {@link IWorkerTransport}.\n */\nexport function createThreadTransport(\n scriptPath: string | URL,\n options?: WorkerOptions,\n): IWorkerTransport {\n const worker = new Worker(scriptPath, options);\n return {\n postMessage(message) {\n worker.postMessage(message);\n },\n on(event, listener) {\n worker.on(event, listener as (...args: unknown[]) => void);\n },\n off(event, listener) {\n worker.off(event, listener as (...args: unknown[]) => void);\n },\n async terminate() {\n return await worker.terminate();\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;AA4CA,SAAgB,sBACd,YACA,SACkB;CAClB,MAAM,SAAS,IAAI,OAAO,YAAY,OAAO;CAC7C,OAAO;EACL,YAAY,SAAS;GACnB,OAAO,YAAY,OAAO;EAC5B;EACA,GAAG,OAAO,UAAU;GAClB,OAAO,GAAG,OAAO,QAAwC;EAC3D;EACA,IAAI,OAAO,UAAU;GACnB,OAAO,IAAI,OAAO,QAAwC;EAC5D;EACA,MAAM,YAAY;GAChB,OAAO,MAAM,OAAO,UAAU;EAChC;CACF;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
1
|
+
import { i as fromErrorInfo } from "./forwarding-logger-ByfBFgMS.js";
|
|
2
|
+
import { a as WorkerLoadModelFailedError, i as WorkerInitFailedError, n as WorkerBusyError, o as WorkerShutdownTimeoutError, r as WorkerExitedError, t as WorkerAbortTimeoutError } from "./errors-BM_ULVWd.js";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
//#region src/executor/worker/worker-handle.ts
|
|
5
5
|
const DEFAULT_ABORT_GRACE_MS = 5e3;
|
|
@@ -57,9 +57,10 @@ var WorkerHandle = class {
|
|
|
57
57
|
workerId: this.workerId,
|
|
58
58
|
poolConfig: this.initPayload.poolConfig,
|
|
59
59
|
db: this.initPayload.db,
|
|
60
|
-
signatureVerifier: this.initPayload.signatureVerifier,
|
|
61
60
|
models: this.initPayload.models,
|
|
62
|
-
executorConfig: this.initPayload.executorConfig
|
|
61
|
+
executorConfig: this.initPayload.executorConfig,
|
|
62
|
+
signer: this.initPayload.signer,
|
|
63
|
+
trustPolicy: this.initPayload.trustPolicy
|
|
63
64
|
});
|
|
64
65
|
await ready;
|
|
65
66
|
this.phase = "ready";
|
|
@@ -95,10 +96,12 @@ var WorkerHandle = class {
|
|
|
95
96
|
}
|
|
96
97
|
});
|
|
97
98
|
});
|
|
98
|
-
if (signal)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
if (signal) {
|
|
100
|
+
if (signal.aborted) this.abort(correlationId, "aborted before dispatch");
|
|
101
|
+
else {
|
|
102
|
+
abortListener = () => this.abort(correlationId, "caller signal");
|
|
103
|
+
signal.addEventListener("abort", abortListener, { once: true });
|
|
104
|
+
}
|
|
102
105
|
}
|
|
103
106
|
this.transport.postMessage({
|
|
104
107
|
type: "execute",
|
|
@@ -207,6 +210,13 @@ var WorkerHandle = class {
|
|
|
207
210
|
});
|
|
208
211
|
return promise;
|
|
209
212
|
}
|
|
213
|
+
evictPurged(documentIds) {
|
|
214
|
+
if (this.phase !== "ready" || documentIds.length === 0) return;
|
|
215
|
+
this.transport.postMessage({
|
|
216
|
+
type: "evict-purged",
|
|
217
|
+
documentIds
|
|
218
|
+
});
|
|
219
|
+
}
|
|
210
220
|
isIdle() {
|
|
211
221
|
return this.inFlight === null && this.phase === "ready";
|
|
212
222
|
}
|
|
@@ -246,7 +256,6 @@ var WorkerHandle = class {
|
|
|
246
256
|
case "pool-acquire-samples":
|
|
247
257
|
this.handlePoolAcquireSamples(msg);
|
|
248
258
|
return;
|
|
249
|
-
default:
|
|
250
259
|
}
|
|
251
260
|
}
|
|
252
261
|
handlePoolAcquireSamples(msg) {
|
|
@@ -273,13 +282,17 @@ var WorkerHandle = class {
|
|
|
273
282
|
clearTimeout(this.abortTimer);
|
|
274
283
|
this.abortTimer = null;
|
|
275
284
|
}
|
|
276
|
-
const outcome = msg.error ? {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
285
|
+
const outcome = msg.error ? {
|
|
286
|
+
result: {
|
|
287
|
+
...msg.result,
|
|
288
|
+
success: false,
|
|
289
|
+
error: fromErrorInfo(msg.error)
|
|
290
|
+
},
|
|
291
|
+
signatureRefusals: msg.signatureRefusals
|
|
292
|
+
} : {
|
|
281
293
|
result: msg.result,
|
|
282
|
-
writeReady: msg.writeReady
|
|
294
|
+
writeReady: msg.writeReady,
|
|
295
|
+
signatureRefusals: msg.signatureRefusals
|
|
283
296
|
};
|
|
284
297
|
entry.resolve(outcome);
|
|
285
298
|
if (this.phase === "shutting-down") {
|
|
@@ -328,7 +341,7 @@ var WorkerHandle = class {
|
|
|
328
341
|
};
|
|
329
342
|
}
|
|
330
343
|
handleTransportError(err) {
|
|
331
|
-
this.logger.error(`worker ${this.workerId} transport error:
|
|
344
|
+
this.logger.error(`worker ${this.workerId} transport error: @message`, err.message, err);
|
|
332
345
|
}
|
|
333
346
|
handleExit(code) {
|
|
334
347
|
if (this.phase === "terminated") return;
|
|
@@ -381,4 +394,4 @@ var WorkerHandle = class {
|
|
|
381
394
|
//#endregion
|
|
382
395
|
export { WorkerHandle };
|
|
383
396
|
|
|
384
|
-
//# sourceMappingURL=worker-handle-
|
|
397
|
+
//# sourceMappingURL=worker-handle-CN2-oRv-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-handle-CN2-oRv-.js","names":[],"sources":["../src/executor/worker/worker-handle.ts"],"sourcesContent":["/**\n * Parent-side IPC wrapper around a single executor worker.\n *\n * Implements {@link IExecutorWorker} on top of an injectable\n * {@link IWorkerTransport}. The handle owns one worker's lifecycle (init ->\n * ready -> execute/result rounds -> abort/shutdown -> terminate) and bounds\n * its in-flight slot to a single job — `SimpleJobExecutor` is single-threaded\n * inside the worker, and concurrent dispatches would race its caches.\n *\n * @see Executor Worker Pool Design wiki page\n * (Powerhouse board wiki id: d400d711-f07e-4389-a226-4e9fdd4fa8ba)\n */\n\nimport type { ILogger } from \"document-model\";\nimport { randomUUID } from \"node:crypto\";\nimport type {\n IExecutorWorker,\n WorkerExecutionOutcome,\n WorkerInFlightSnapshot,\n} from \"../interfaces.js\";\nimport type { Job } from \"../../queue/types.js\";\nimport type { JobExecutorConfig } from \"../types.js\";\nimport { fromErrorInfo } from \"./error-info.js\";\nimport {\n WorkerAbortTimeoutError,\n WorkerBusyError,\n WorkerExitedError,\n WorkerInitFailedError,\n WorkerLoadModelFailedError,\n WorkerShutdownTimeoutError,\n} from \"./errors.js\";\nimport type { ForwardingPoolInstrumentation } from \"../../storage/pool-instrumentation.js\";\nimport type {\n DbConfig,\n FactorySpec,\n HeartbeatMessage,\n LogMessage,\n MetricsMessage,\n ModelLoadFailedMessage,\n ModelLoadedMessage,\n ModelManifestEntry,\n PoolAcquireSamplesMessage,\n ResultMessage,\n WorkerMessage,\n WorkerPoolConfig,\n} from \"./protocol.js\";\nimport type { IWorkerTransport, WorkerTransportListener } from \"./transport.js\";\n\nconst DEFAULT_ABORT_GRACE_MS = 5_000;\nconst DEFAULT_SHUTDOWN_GRACE_MS = 5_000;\n\n/**\n * Payload the parent ships in the `init` message (everything except the\n * envelope fields the handle fills in itself).\n */\nexport type WorkerInitPayload = {\n poolConfig: WorkerPoolConfig;\n db: DbConfig;\n models: ModelManifestEntry[];\n /** Omitted = the worker builds its executor with the built-in defaults. */\n executorConfig?: JobExecutorConfig;\n /** Builds the worker's signer for synthesized operations. */\n signer?: FactorySpec;\n /** Builds the worker's signature trust policy. */\n trustPolicy?: FactorySpec;\n};\n\nexport type WorkerHandleOptions = {\n workerId: string;\n index: number;\n transport: IWorkerTransport;\n initPayload: WorkerInitPayload;\n logger: ILogger;\n /** Grace period before an outstanding `abort` escalates to terminate. */\n abortGraceMs?: number;\n /** Default grace period applied to graceful `shutdown` when not overridden. */\n defaultShutdownGraceMs?: number;\n /**\n * Forwarding instrumentation the host registers per worker. The handle\n * pumps `pool-acquire-samples` messages into this object so the host's\n * OpenTelemetry instrumentation records acquire-wait latencies as if the\n * worker's pool were local.\n */\n poolInstrumentation?: ForwardingPoolInstrumentation;\n};\n\ntype PendingEntry =\n | {\n kind: \"init\";\n resolve: () => void;\n reject: (err: Error) => void;\n }\n | {\n kind: \"execute\";\n jobId: string;\n resolve: (outcome: WorkerExecutionOutcome) => void;\n reject: (err: Error) => void;\n }\n | {\n kind: \"shutdown\";\n resolve: () => void;\n reject: (err: Error) => void;\n }\n | {\n kind: \"load-model\";\n documentType: string;\n version: string;\n resolve: () => void;\n reject: (err: Error) => void;\n };\n\ntype Phase = \"fresh\" | \"starting\" | \"ready\" | \"shutting-down\" | \"terminated\";\n\nexport class WorkerHandle implements IExecutorWorker {\n readonly workerId: string;\n readonly index: number;\n\n private readonly transport: IWorkerTransport;\n private readonly initPayload: WorkerInitPayload;\n private readonly logger: ILogger;\n private readonly abortGraceMs: number;\n private readonly defaultShutdownGraceMs: number;\n private readonly poolInstrumentation?: ForwardingPoolInstrumentation;\n\n private readonly pending = new Map<string, PendingEntry>();\n private inFlight: { correlationId: string; jobId: string } | null = null;\n private phase: Phase = \"fresh\";\n private lastExitError: Error | null = null;\n private lastCorrelationId: string | null = null;\n private abortTimer: NodeJS.Timeout | null = null;\n private lastHeartbeatAt: number | null = null;\n private lastMetrics: {\n counters: Record<string, number>;\n gauges: Record<string, number>;\n timestamp: number;\n } | null = null;\n\n private readonly onMessage: WorkerTransportListener<\"message\">;\n private readonly onError: WorkerTransportListener<\"error\">;\n private readonly onExit: WorkerTransportListener<\"exit\">;\n\n constructor(options: WorkerHandleOptions) {\n this.workerId = options.workerId;\n this.index = options.index;\n this.transport = options.transport;\n this.initPayload = options.initPayload;\n this.logger = options.logger;\n this.abortGraceMs = options.abortGraceMs ?? DEFAULT_ABORT_GRACE_MS;\n this.defaultShutdownGraceMs =\n options.defaultShutdownGraceMs ?? DEFAULT_SHUTDOWN_GRACE_MS;\n this.poolInstrumentation = options.poolInstrumentation;\n\n this.onMessage = (msg) => this.handleMessage(msg);\n this.onError = (err) => this.handleTransportError(err);\n this.onExit = (code) => this.handleExit(code);\n\n this.transport.on(\"message\", this.onMessage);\n this.transport.on(\"error\", this.onError);\n this.transport.on(\"exit\", this.onExit);\n }\n\n public async start(): Promise<void> {\n if (this.phase !== \"fresh\") {\n throw new WorkerInitFailedError(\n this.workerId,\n `cannot start worker in phase ${this.phase}`,\n );\n }\n this.phase = \"starting\";\n const correlationId = this.nextCorrelationId();\n const ready = new Promise<void>((resolve, reject) => {\n this.pending.set(correlationId, {\n kind: \"init\",\n resolve,\n reject,\n });\n });\n this.transport.postMessage({\n type: \"init\",\n correlationId,\n workerId: this.workerId,\n poolConfig: this.initPayload.poolConfig,\n db: this.initPayload.db,\n models: this.initPayload.models,\n executorConfig: this.initPayload.executorConfig,\n signer: this.initPayload.signer,\n trustPolicy: this.initPayload.trustPolicy,\n });\n await ready;\n this.phase = \"ready\";\n }\n\n public execute(\n job: Job,\n signal?: AbortSignal,\n ): Promise<WorkerExecutionOutcome> {\n if (this.phase === \"terminated\") {\n return Promise.reject(\n this.lastExitError ??\n new WorkerExitedError(this.workerId, -1, this.lastCorrelationId),\n );\n }\n if (this.phase !== \"ready\") {\n return Promise.reject(\n new WorkerInitFailedError(\n this.workerId,\n `worker not ready (phase=${this.phase})`,\n ),\n );\n }\n if (this.inFlight !== null) {\n return Promise.reject(new WorkerBusyError(this.workerId, job.id));\n }\n\n const correlationId = this.nextCorrelationId();\n this.lastCorrelationId = correlationId;\n this.inFlight = { correlationId, jobId: job.id };\n\n let abortListener: (() => void) | null = null;\n const detachSignal = () => {\n if (signal && abortListener) {\n signal.removeEventListener(\"abort\", abortListener);\n abortListener = null;\n }\n };\n\n const promise = new Promise<WorkerExecutionOutcome>((resolve, reject) => {\n this.pending.set(correlationId, {\n kind: \"execute\",\n jobId: job.id,\n resolve: (outcome) => {\n detachSignal();\n resolve(outcome);\n },\n reject: (err) => {\n detachSignal();\n reject(err);\n },\n });\n });\n\n if (signal) {\n if (signal.aborted) {\n this.abort(correlationId, \"aborted before dispatch\");\n } else {\n abortListener = () => this.abort(correlationId, \"caller signal\");\n signal.addEventListener(\"abort\", abortListener, { once: true });\n }\n }\n\n this.transport.postMessage({\n type: \"execute\",\n correlationId,\n job,\n });\n\n return promise;\n }\n\n public abort(correlationId: string, reason?: string): void {\n if (this.phase === \"terminated\") {\n return;\n }\n if (!this.inFlight || this.inFlight.correlationId !== correlationId) {\n return;\n }\n if (this.abortTimer) {\n return;\n }\n this.transport.postMessage({\n type: \"abort\",\n correlationId: this.nextCorrelationId(),\n targetCorrelationId: correlationId,\n reason,\n });\n this.abortTimer = setTimeout(() => {\n this.abortTimer = null;\n const entry = this.pending.get(correlationId);\n if (!entry || entry.kind !== \"execute\") {\n return;\n }\n const err = new WorkerAbortTimeoutError(\n this.workerId,\n correlationId,\n this.abortGraceMs,\n );\n this.failPending(correlationId, err);\n this.inFlight = null;\n void this.forceTerminate(err);\n }, this.abortGraceMs);\n }\n\n public async shutdown(graceful: boolean, graceMs?: number): Promise<void> {\n if (this.phase === \"terminated\") {\n return;\n }\n if (!graceful) {\n this.phase = \"shutting-down\";\n await this.forceTerminate(null);\n return;\n }\n\n const effectiveGrace = graceMs ?? this.defaultShutdownGraceMs;\n this.phase = \"shutting-down\";\n const correlationId = this.nextCorrelationId();\n const drained = new Promise<void>((resolve, reject) => {\n this.pending.set(correlationId, {\n kind: \"shutdown\",\n resolve,\n reject,\n });\n });\n this.transport.postMessage({\n type: \"shutdown\",\n correlationId,\n graceMs: effectiveGrace,\n });\n\n let timer!: NodeJS.Timeout;\n const timeout = new Promise<void>((_, reject) => {\n timer = setTimeout(() => {\n reject(new WorkerShutdownTimeoutError(this.workerId, effectiveGrace));\n }, effectiveGrace);\n });\n\n try {\n await Promise.race([drained, timeout]);\n } catch (err) {\n this.logger.warn(\n `worker ${this.workerId} shutdown timed out after ${effectiveGrace}ms`,\n err,\n );\n } finally {\n clearTimeout(timer);\n }\n\n await this.forceTerminate(null);\n }\n\n public loadModel(\n entry: ModelManifestEntry,\n signal?: AbortSignal,\n ): Promise<void> {\n if (this.phase === \"terminated\") {\n return Promise.reject(\n this.lastExitError ??\n new WorkerExitedError(this.workerId, -1, this.lastCorrelationId),\n );\n }\n if (this.phase !== \"ready\") {\n return Promise.reject(\n new WorkerInitFailedError(\n this.workerId,\n `worker not ready (phase=${this.phase})`,\n ),\n );\n }\n\n const correlationId = this.nextCorrelationId();\n let abortListener: (() => void) | null = null;\n const detachSignal = () => {\n if (signal && abortListener) {\n signal.removeEventListener(\"abort\", abortListener);\n abortListener = null;\n }\n };\n\n const promise = new Promise<void>((resolve, reject) => {\n this.pending.set(correlationId, {\n kind: \"load-model\",\n documentType: entry.documentType,\n version: entry.version,\n resolve: () => {\n detachSignal();\n resolve();\n },\n reject: (err) => {\n detachSignal();\n reject(err);\n },\n });\n });\n\n if (signal) {\n if (signal.aborted) {\n this.failPending(\n correlationId,\n new WorkerLoadModelFailedError(\n this.workerId,\n entry.documentType,\n entry.version,\n \"aborted before dispatch\",\n ),\n );\n return promise;\n }\n abortListener = () => {\n this.failPending(\n correlationId,\n new WorkerLoadModelFailedError(\n this.workerId,\n entry.documentType,\n entry.version,\n \"caller signal\",\n ),\n );\n };\n signal.addEventListener(\"abort\", abortListener, { once: true });\n }\n\n this.transport.postMessage({\n type: \"load-model\",\n correlationId,\n model: entry,\n });\n\n return promise;\n }\n\n public evictPurged(documentIds: string[]): void {\n if (this.phase !== \"ready\" || documentIds.length === 0) {\n return;\n }\n this.transport.postMessage({ type: \"evict-purged\", documentIds });\n }\n\n public isIdle(): boolean {\n return this.inFlight === null && this.phase === \"ready\";\n }\n\n public getInFlight(): WorkerInFlightSnapshot | null {\n if (!this.inFlight) {\n return null;\n }\n return {\n correlationId: this.inFlight.correlationId,\n jobId: this.inFlight.jobId,\n };\n }\n\n private nextCorrelationId(): string {\n return randomUUID();\n }\n\n private handleMessage(msg: WorkerMessage): void {\n switch (msg.type) {\n case \"ready\":\n this.handleReady(msg.correlationId);\n return;\n case \"result\":\n this.handleResult(msg);\n return;\n case \"model-loaded\":\n this.handleModelLoaded(msg);\n return;\n case \"model-load-failed\":\n this.handleModelLoadFailed(msg);\n return;\n case \"log\":\n this.handleLog(msg);\n return;\n case \"heartbeat\":\n this.handleHeartbeat(msg);\n return;\n case \"metrics\":\n this.handleMetrics(msg);\n return;\n case \"pool-acquire-samples\":\n this.handlePoolAcquireSamples(msg);\n return;\n default: {\n const exhaustive: never = msg;\n void exhaustive;\n }\n }\n }\n\n private handlePoolAcquireSamples(msg: PoolAcquireSamplesMessage): void {\n if (!this.poolInstrumentation) {\n return;\n }\n this.poolInstrumentation.updateStats({\n size: msg.size,\n idle: msg.idle,\n waiting: msg.waiting,\n });\n this.poolInstrumentation.pushSamples(msg.durations);\n }\n\n private handleReady(correlationId: string): void {\n const entry = this.pending.get(correlationId);\n if (!entry || entry.kind !== \"init\") {\n return;\n }\n this.pending.delete(correlationId);\n entry.resolve();\n }\n\n private handleResult(msg: ResultMessage): void {\n const entry = this.pending.get(msg.correlationId);\n if (!entry || entry.kind !== \"execute\") {\n return;\n }\n this.pending.delete(msg.correlationId);\n if (this.inFlight?.correlationId === msg.correlationId) {\n this.inFlight = null;\n }\n if (this.abortTimer) {\n clearTimeout(this.abortTimer);\n this.abortTimer = null;\n }\n\n const outcome: WorkerExecutionOutcome = msg.error\n ? {\n result: {\n ...msg.result,\n success: false,\n error: fromErrorInfo(msg.error),\n },\n signatureRefusals: msg.signatureRefusals,\n }\n : {\n result: msg.result,\n writeReady: msg.writeReady,\n signatureRefusals: msg.signatureRefusals,\n };\n entry.resolve(outcome);\n\n if (this.phase === \"shutting-down\") {\n const shutdownEntry = [...this.pending.values()].find(\n (e) => e.kind === \"shutdown\",\n );\n if (shutdownEntry) {\n shutdownEntry.resolve();\n }\n }\n }\n\n private handleModelLoaded(msg: ModelLoadedMessage): void {\n const entry = this.pending.get(msg.correlationId);\n if (!entry || entry.kind !== \"load-model\") {\n return;\n }\n this.pending.delete(msg.correlationId);\n entry.resolve();\n }\n\n private handleModelLoadFailed(msg: ModelLoadFailedMessage): void {\n const entry = this.pending.get(msg.correlationId);\n if (!entry || entry.kind !== \"load-model\") {\n return;\n }\n this.pending.delete(msg.correlationId);\n entry.reject(\n new WorkerLoadModelFailedError(\n this.workerId,\n msg.documentType,\n msg.version,\n msg.error.message,\n { cause: fromErrorInfo(msg.error) },\n ),\n );\n }\n\n private handleLog(msg: LogMessage): void {\n const args = msg.args;\n switch (msg.level) {\n case \"debug\":\n this.logger.debug(msg.message, ...args);\n return;\n case \"info\":\n this.logger.info(msg.message, ...args);\n return;\n case \"warn\":\n this.logger.warn(msg.message, ...args);\n return;\n case \"error\":\n this.logger.error(msg.message, ...args);\n return;\n default: {\n const exhaustive: never = msg.level;\n void exhaustive;\n }\n }\n }\n\n private handleHeartbeat(msg: HeartbeatMessage): void {\n this.lastHeartbeatAt = msg.timestamp;\n }\n\n private handleMetrics(msg: MetricsMessage): void {\n this.lastMetrics = {\n counters: msg.counters,\n gauges: msg.gauges,\n timestamp: msg.timestamp,\n };\n }\n\n private handleTransportError(err: Error): void {\n this.logger.error(\n `worker ${this.workerId} transport error: @message`,\n err.message,\n err,\n );\n }\n\n private handleExit(code: number): void {\n if (this.phase === \"terminated\") {\n return;\n }\n const wasGraceful = this.phase === \"shutting-down\" && code === 0;\n this.phase = \"terminated\";\n const err = wasGraceful\n ? null\n : new WorkerExitedError(this.workerId, code, this.lastCorrelationId);\n this.lastExitError = err;\n if (this.abortTimer) {\n clearTimeout(this.abortTimer);\n this.abortTimer = null;\n }\n this.detachTransportListeners();\n this.drainPending(err);\n this.inFlight = null;\n }\n\n private detachTransportListeners(): void {\n this.transport.off(\"message\", this.onMessage);\n this.transport.off(\"error\", this.onError);\n this.transport.off(\"exit\", this.onExit);\n }\n\n private drainPending(err: Error | null): void {\n for (const [, entry] of this.pending) {\n if (err) {\n entry.reject(err);\n } else if (entry.kind === \"shutdown\") {\n entry.resolve();\n } else if (entry.kind === \"init\") {\n entry.reject(new WorkerInitFailedError(this.workerId, \"worker exited\"));\n } else if (entry.kind === \"load-model\") {\n entry.reject(\n new WorkerLoadModelFailedError(\n this.workerId,\n entry.documentType,\n entry.version,\n \"worker exited before responding\",\n ),\n );\n } else {\n entry.reject(\n new WorkerExitedError(this.workerId, 0, this.lastCorrelationId),\n );\n }\n }\n this.pending.clear();\n }\n\n private failPending(correlationId: string, err: Error): void {\n const entry = this.pending.get(correlationId);\n if (!entry) {\n return;\n }\n this.pending.delete(correlationId);\n entry.reject(err);\n }\n\n private async forceTerminate(reason: Error | null): Promise<void> {\n if (this.phase === \"terminated\") {\n return;\n }\n try {\n await this.transport.terminate();\n } catch (err) {\n this.logger.warn(\n `worker ${this.workerId} terminate threw: ${(err as Error).message}`,\n );\n }\n const phaseAfter = this.phase as Phase;\n if (phaseAfter === \"terminated\") {\n return;\n }\n this.phase = \"terminated\";\n this.lastExitError = reason;\n this.detachTransportListeners();\n this.drainPending(reason);\n this.inFlight = null;\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/reactor",
|
|
3
|
-
"version": "6.2.3-dev.
|
|
3
|
+
"version": "6.2.3-dev.50",
|
|
4
4
|
"description": "Core Powerhouse reactor — stores documents, resolves conflicts, and reprocesses operation histories. Supports local, cloud, and decentralized storage backends.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/powerhouse-inc/powerhouse",
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
"source": "./index.ts",
|
|
15
15
|
"types": "./dist/index.d.ts",
|
|
16
16
|
"import": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./rpc": {
|
|
19
|
+
"source": "./src/rpc/index.ts",
|
|
20
|
+
"types": "./dist/rpc.d.ts",
|
|
21
|
+
"import": "./dist/rpc.js"
|
|
17
22
|
}
|
|
18
23
|
},
|
|
19
24
|
"files": [
|
|
@@ -42,19 +47,20 @@
|
|
|
42
47
|
"@electric-sql/pglite": "0.3.15",
|
|
43
48
|
"pg": "8.18.0",
|
|
44
49
|
"@sindresorhus/fnv1a": "3.1.0",
|
|
45
|
-
"@powerhousedao/shared": "6.2.3-dev.
|
|
46
|
-
"document-model": "6.2.3-dev.
|
|
50
|
+
"@powerhousedao/shared": "6.2.3-dev.50",
|
|
51
|
+
"document-model": "6.2.3-dev.50"
|
|
47
52
|
},
|
|
48
53
|
"devDependencies": {
|
|
49
|
-
"@
|
|
54
|
+
"@informalsystems/quint": "0.32.0",
|
|
55
|
+
"@types/cross-spawn": "6.0.6",
|
|
50
56
|
"@types/pg": "8.16.0",
|
|
51
|
-
"
|
|
52
|
-
"
|
|
57
|
+
"cross-spawn": "7.0.6",
|
|
58
|
+
"@vitest/coverage-v8": "5.0.3",
|
|
53
59
|
"tinybench": "^2.9.0",
|
|
54
|
-
"tsx": "4.
|
|
55
|
-
"vitest": "
|
|
60
|
+
"tsx": "4.23.13",
|
|
61
|
+
"vitest": "5.0.3",
|
|
56
62
|
"@types/bun": "1.3.8",
|
|
57
|
-
"tsdown": "0.
|
|
63
|
+
"tsdown": "0.23.0",
|
|
58
64
|
"zod": "4.3.6"
|
|
59
65
|
},
|
|
60
66
|
"homepage": "https://academy.vetra.io/academy/Reference/Reactor/WorkingWithTheReactor",
|
|
@@ -62,31 +68,41 @@
|
|
|
62
68
|
"build": "tsdown",
|
|
63
69
|
"test": "vitest run --coverage --printConsoleTrace=true --silent=false",
|
|
64
70
|
"test:watch": "vitest --coverage",
|
|
65
|
-
"lint": "
|
|
71
|
+
"lint": "cd ../.. && oxlint packages/reactor",
|
|
66
72
|
"bench": "vitest bench --run",
|
|
67
73
|
"bench:record": "tsx bench/records/run-record-all.ts",
|
|
68
74
|
"bench:auth": "vitest bench --run bench/auth-scope",
|
|
69
|
-
"bench:auth:record": "vitest bench --run bench/auth-scope --
|
|
70
|
-
"bench:auth:compare": "vitest bench --run bench/auth-scope
|
|
71
|
-
"bench:
|
|
72
|
-
"bench:
|
|
73
|
-
"bench:queue
|
|
74
|
-
"bench:
|
|
75
|
+
"bench:auth:record": "BENCH_SAVE=bench/results/baselines vitest bench --run bench/auth-scope --reporter=default --reporter=json --outputFile.json=bench/results/auth-scope.json",
|
|
76
|
+
"bench:auth:compare": "BENCH_COMPARE=bench/results/baselines vitest bench --run bench/auth-scope",
|
|
77
|
+
"bench:auth-storage:record": "vitest bench --run bench/auth-gate-storage --reporter=default --reporter=json --outputFile.json=bench/results/auth-gate-storage.json",
|
|
78
|
+
"bench:events:record": "vitest bench --run bench/event-bus --reporter=default --reporter=json --outputFile.json=bench/results/event-bus.json",
|
|
79
|
+
"bench:queue:record": "vitest bench --run bench/queue-perf --reporter=default --reporter=json --outputFile.json=bench/results/queue-perf.json",
|
|
80
|
+
"bench:queue-only:record": "vitest bench --run bench/queue-only --reporter=default --reporter=json --outputFile.json=bench/results/queue-only.json",
|
|
81
|
+
"bench:cache:record": "vitest bench --run bench/write-cache --reporter=default --reporter=json --outputFile.json=bench/results/write-cache.json",
|
|
82
|
+
"bench:processors": "vitest bench --run bench/processor-delivery",
|
|
83
|
+
"bench:processors:record": "vitest bench --run bench/processor-delivery --reporter=default --reporter=json --outputFile.json=bench/results/processor-delivery.json",
|
|
75
84
|
"bench:sync": "node --import tsx bench/two-reactor-sync.ts",
|
|
76
85
|
"bench:sync:record": "node --import tsx bench/two-reactor-sync.ts --record",
|
|
77
86
|
"bench:sync:smoke": "node --import tsx bench/two-reactor-sync.ts --smoke",
|
|
78
87
|
"clean": "rimraf dist",
|
|
79
88
|
"clean:node_modules": "rimraf node_modules",
|
|
80
|
-
"claude": "pnpm build && pnpm test && pnpm exec
|
|
89
|
+
"claude": "pnpm build && pnpm test && pnpm exec oxfmt \"**/*.ts\" && pnpm lint",
|
|
81
90
|
"migrate": "tsx src/storage/migrations/run-migrations.ts",
|
|
82
91
|
"migrate:status": "tsx src/storage/migrations/run-migrations.ts status",
|
|
83
92
|
"preflight:auth": "tsx src/admin/run-stream-order-check.ts",
|
|
93
|
+
"catchup": "tsx src/admin/run-catchup.ts",
|
|
84
94
|
"bench:records": "tsx bench/records/run-records.ts",
|
|
85
95
|
"bench:records:verify": "tsx bench/records/run-records.ts verify",
|
|
86
96
|
"bench:records:from-vitest": "tsx bench/records/run-from-vitest.ts",
|
|
87
97
|
"bench:fix": "tsx bench/fix/run-fix.ts",
|
|
88
98
|
"bench:ui": "node bench/ui/serve.mjs",
|
|
89
99
|
"docker:up": "docker compose up -d",
|
|
90
|
-
"docker:down": "docker compose down"
|
|
100
|
+
"docker:down": "docker compose down",
|
|
101
|
+
"spec:typecheck": "cd spec && quint typecheck PeerAgreement.qnt && quint typecheck PeerAgreementTest.qnt",
|
|
102
|
+
"spec:test": "cd spec && quint test --max-samples=100 PeerAgreementTest.qnt",
|
|
103
|
+
"spec:sim": "sh spec/scripts/sim.sh",
|
|
104
|
+
"spec:verify": "sh spec/scripts/verify-all.sh",
|
|
105
|
+
"spec:check": "pnpm spec:typecheck && pnpm spec:test && pnpm spec:sim && pnpm spec:verify",
|
|
106
|
+
"spec:trace": "python3 spec/scripts/trace.py"
|
|
91
107
|
}
|
|
92
108
|
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { _ as DocumentMetaCache, c as KyselyKeyframeStore, f as KyselyExecutionScope, g as KyselyOperationIndex, h as KyselyWriteCache, l as DocumentModelRegistry, m as EventBus, n as REACTOR_SCHEMA, s as KyselyOperationStore, t as DEFAULT_DRIVE_CONTAINER_TYPES, u as SimpleJobExecutor, v as CollectionMembershipCache } from "./drive-container-types-yZrksiJR.js";
|
|
2
|
-
import { n as ReactorEventTypes } from "./types-DMKLa0Ok.js";
|
|
3
|
-
//#region src/executor/worker/build-worker-executor.ts
|
|
4
|
-
async function defaultLoadFactory(spec) {
|
|
5
|
-
const ref = spec.module;
|
|
6
|
-
const exported = (await ("filePath" in ref ? import(new URL(`file://${ref.filePath}`).href) : import(ref.packageName)))[ref.exportName];
|
|
7
|
-
if (typeof exported === "function") return exported(spec.initArgs);
|
|
8
|
-
return exported;
|
|
9
|
-
}
|
|
10
|
-
async function loadModelManifest(entries, loadFactory, registry, logger) {
|
|
11
|
-
for (const entry of entries) {
|
|
12
|
-
let module;
|
|
13
|
-
try {
|
|
14
|
-
module = await loadFactory(entry.spec);
|
|
15
|
-
} catch (error) {
|
|
16
|
-
logger.error("worker failed to load document model: @entry @error", entry, error);
|
|
17
|
-
throw error;
|
|
18
|
-
}
|
|
19
|
-
const [result] = registry.registerModules(module);
|
|
20
|
-
if (result.status === "error") {
|
|
21
|
-
logger.error("worker failed to register document model: @entry @error", entry, result.error);
|
|
22
|
-
throw result.error;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Assembles the in-worker storage stack plus a {@link SimpleJobExecutor}
|
|
28
|
-
* bound to a pre-built Kysely instance. The parent owns the wire protocol
|
|
29
|
-
* and routing; the worker owns everything below `SimpleJobExecutor`.
|
|
30
|
-
*
|
|
31
|
-
* The local event bus exists only to satisfy the executor's contract: its
|
|
32
|
-
* JOB_WRITE_READY emissions are captured here and shipped to the parent
|
|
33
|
-
* via {@link WorkerExecutorStack.takeLastWriteReady}.
|
|
34
|
-
*/
|
|
35
|
-
async function buildWorkerExecutor(options) {
|
|
36
|
-
const { init, database: baseDatabase, logger } = options;
|
|
37
|
-
const driveContainerTypes = options.driveContainerTypes ?? DEFAULT_DRIVE_CONTAINER_TYPES;
|
|
38
|
-
const loadFactory = options.loadFactory ?? defaultLoadFactory;
|
|
39
|
-
const registry = new DocumentModelRegistry();
|
|
40
|
-
await loadModelManifest(init.models, loadFactory, registry, logger);
|
|
41
|
-
let signatureVerifier;
|
|
42
|
-
if (init.signatureVerifier) try {
|
|
43
|
-
signatureVerifier = await loadFactory(init.signatureVerifier);
|
|
44
|
-
} catch (error) {
|
|
45
|
-
logger.error("worker failed to load signature verifier: @spec @error", init.signatureVerifier, error);
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
48
|
-
const database = baseDatabase.withSchema(REACTOR_SCHEMA);
|
|
49
|
-
const operationStore = new KyselyOperationStore(database);
|
|
50
|
-
const keyframeStore = new KyselyKeyframeStore(database);
|
|
51
|
-
const writeCache = new KyselyWriteCache(keyframeStore, operationStore, registry, {
|
|
52
|
-
maxDocuments: 100,
|
|
53
|
-
ringBufferSize: 10,
|
|
54
|
-
keyframeInterval: 10
|
|
55
|
-
});
|
|
56
|
-
await writeCache.startup();
|
|
57
|
-
const operationIndex = new KyselyOperationIndex(database);
|
|
58
|
-
const documentMetaCache = new DocumentMetaCache(operationStore, { maxDocuments: 1e3 });
|
|
59
|
-
await documentMetaCache.startup();
|
|
60
|
-
const collectionMembershipCache = new CollectionMembershipCache(operationIndex);
|
|
61
|
-
const executionScope = new KyselyExecutionScope(database, operationStore, operationIndex, keyframeStore, writeCache, documentMetaCache, collectionMembershipCache);
|
|
62
|
-
const eventBus = new EventBus();
|
|
63
|
-
let lastWriteReady = null;
|
|
64
|
-
eventBus.subscribe(ReactorEventTypes.JOB_WRITE_READY, (_t, event) => {
|
|
65
|
-
lastWriteReady = {
|
|
66
|
-
operations: event.operations,
|
|
67
|
-
jobMeta: event.jobMeta
|
|
68
|
-
};
|
|
69
|
-
});
|
|
70
|
-
return {
|
|
71
|
-
executor: new SimpleJobExecutor(logger, registry, operationStore, eventBus, writeCache, operationIndex, documentMetaCache, collectionMembershipCache, driveContainerTypes, options.executorConfig ?? {}, signatureVerifier, executionScope),
|
|
72
|
-
registry,
|
|
73
|
-
takeLastWriteReady() {
|
|
74
|
-
const captured = lastWriteReady;
|
|
75
|
-
lastWriteReady = null;
|
|
76
|
-
return captured;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
//#endregion
|
|
81
|
-
export { defaultLoadFactory as n, buildWorkerExecutor as t };
|
|
82
|
-
|
|
83
|
-
//# sourceMappingURL=build-worker-executor-DnU3ZU4H.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build-worker-executor-DnU3ZU4H.js","names":[],"sources":["../src/executor/worker/build-worker-executor.ts"],"sourcesContent":["import type {\n DocumentModelModule,\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} from \"../../events/types.js\";\nimport { DocumentModelRegistry } from \"../../registry/implementation.js\";\nimport type { JobMeta } from \"../../shared/types.js\";\nimport type { SignatureVerificationHandler } from \"../../signer/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 { JobExecutorConfig } from \"../types.js\";\nimport type {\n FactorySpec,\n InitMessage,\n ModelManifestEntry,\n} from \"./protocol.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};\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\nexport async function defaultLoadFactory(spec: FactorySpec): Promise<unknown> {\n const ref = spec.module;\n const specifier =\n \"filePath\" in ref\n ? new URL(`file://${ref.filePath}`).href\n : ref.packageName;\n const mod = (await import(specifier)) as Record<string, unknown>;\n const exported = mod[ref.exportName];\n if (typeof exported === \"function\") {\n return (exported as (args: unknown) => unknown)(spec.initArgs);\n }\n return exported;\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 signatureVerifier: SignatureVerificationHandler | undefined;\n if (init.signatureVerifier) {\n try {\n signatureVerifier = (await loadFactory(\n init.signatureVerifier,\n )) as SignatureVerificationHandler;\n } catch (error) {\n logger.error(\n \"worker failed to load signature verifier: @spec @error\",\n init.signatureVerifier,\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 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 signatureVerifier,\n executionScope,\n );\n\n return {\n executor,\n registry,\n takeLastWriteReady(): WorkerWriteReadyCapture | null {\n const captured = lastWriteReady;\n lastWriteReady = null;\n return captured;\n },\n };\n}\n"],"mappings":";;;AAqEA,eAAsB,mBAAmB,MAAqC;CAC5E,MAAM,MAAM,KAAK;CAMjB,MAAM,YADO,OAHX,cAAc,MAAA,OACV,IAAI,IAAI,UAAU,IAAI,WAAW,CAAC,QAAA,OAClC,IAAI,eAEW,IAAI;AACzB,KAAI,OAAO,aAAa,WACtB,QAAQ,SAAwC,KAAK,SAAS;AAEhE,QAAO;;AAGT,eAAe,kBACb,SACA,aACA,UACA,QACe;AACf,MAAK,MAAM,SAAS,SAAS;EAC3B,IAAI;AACJ,MAAI;AACF,YAAU,MAAM,YAAY,MAAM,KAAK;WAChC,OAAO;AACd,UAAO,MACL,uDACA,OACA,MACD;AACD,SAAM;;EAER,MAAM,CAAC,UAAU,SAAS,gBAAgB,OAAO;AACjD,MAAI,OAAO,WAAW,SAAS;AAC7B,UAAO,MACL,2DACA,OACA,OAAO,MACR;AACD,SAAM,OAAO;;;;;;;;;;;;;AAcnB,eAAsB,oBACpB,SAC8B;CAC9B,MAAM,EAAE,MAAM,UAAU,cAAc,WAAW;CACjD,MAAM,sBACJ,QAAQ,uBAAuB;CACjC,MAAM,cAAc,QAAQ,eAAe;CAE3C,MAAM,WAAW,IAAI,uBAAuB;AAC5C,OAAM,kBAAkB,KAAK,QAAQ,aAAa,UAAU,OAAO;CAEnE,IAAI;AACJ,KAAI,KAAK,kBACP,KAAI;AACF,sBAAqB,MAAM,YACzB,KAAK,kBACN;UACM,OAAO;AACd,SAAO,MACL,0DACA,KAAK,mBACL,MACD;AACD,QAAM;;CAIV,MAAM,WAAW,aAAa,WAAW,eAAe;CACxD,MAAM,iBAAiB,IAAI,qBACzB,SACD;CACD,MAAM,gBAAgB,IAAI,oBACxB,SACD;CAOD,MAAM,aAAa,IAAI,iBACrB,eACA,gBACA,UARoC;EACpC,cAAc;EACd,gBAAgB;EAChB,kBAAkB;EACnB,CAMA;AACD,OAAM,WAAW,SAAS;CAE1B,MAAM,iBAAiB,IAAI,qBACzB,SACD;CAED,MAAM,oBAAoB,IAAI,kBAAkB,gBAAgB,EAC9D,cAAc,KACf,CAAC;AACF,OAAM,kBAAkB,SAAS;CAEjC,MAAM,4BAA4B,IAAI,0BACpC,eACD;CAED,MAAM,iBAAiB,IAAI,qBACzB,UACA,gBACA,gBACA,eACA,YACA,mBACA,0BACD;CAED,MAAM,WAAW,IAAI,UAAU;CAC/B,IAAI,iBAAiD;AACrD,UAAS,UACP,kBAAkB,kBACjB,IAAY,UAA8B;AACzC,mBAAiB;GACf,YAAY,MAAM;GAClB,SAAS,MAAM;GAChB;GAEJ;AAkBD,QAAO;EACL,UAhBe,IAAI,kBACnB,QACA,UACA,gBACA,UACA,YACA,gBACA,mBACA,2BACA,qBAVqB,QAAQ,kBAAkB,EAAE,EAYjD,mBACA,eACD;EAIC;EACA,qBAAqD;GACnD,MAAM,WAAW;AACjB,oBAAiB;AACjB,UAAO;;EAEV"}
|