1// Host-side wrapper for the compute worker: one shared worker, one
2// promise per request. Requests are serviced one at a time in order.
4import type { WorkerRequest, WorkerResponse } from "./worker";
5import type { ResultPoint } from "../harness/resultSchema";
7type Pending = {
8 onPoint?: (point: ResultPoint, index: number, total: number) => void;
9 resolve: (value: never) => void;
10 reject: (err: Error) => void;
11};
13let worker: Worker | null = null;
14let nextId = 1;
15const pending = new Map<number, Pending>();
17function getWorker(): Worker {
18 if (!worker) {
19 worker = new Worker(new URL("./worker.ts", import.meta.url), {
20 type: "module",
21 });
22 worker.onmessage = (e: MessageEvent<WorkerResponse>) => {
23 const msg = e.data;
24 const p = pending.get(msg.id);
25 if (!p) return;
26 if (msg.type === "point") {
27 p.onPoint?.(msg.point, msg.index, msg.total);
28 } else if (msg.type === "sweepDone") {
29 pending.delete(msg.id);
30 (p.resolve as (v: ResultPoint[]) => void)(msg.points);
31 } else if (msg.type === "solutionDone") {
32 pending.delete(msg.id);
33 (p.resolve as (v: { point: ResultPoint; uGrid: Float64Array }) => void)({
34 point: msg.point,
35 uGrid: msg.uGrid,
36 });
37 } else if (msg.type === "error") {
38 pending.delete(msg.id);
39 p.reject(new Error(msg.message));
40 }
41 };
42 }
43 return worker;
44}
46function post(req: WorkerRequest) {
47 getWorker().postMessage(req);
48}
50export function sweepInBrowser(
51 instanceId: string,
52 solverId: string,
53 repeats: number,
54 onPoint: (point: ResultPoint, index: number, total: number) => void
55): Promise<ResultPoint[]> {
56 const id = nextId++;
57 return new Promise((resolve, reject) => {
58 pending.set(id, { onPoint, resolve: resolve as never, reject });
59 post({ type: "sweep", id, instanceId, solverId, repeats });
60 });
61}
63export function solutionInBrowser(
64 instanceId: string,
65 solverId: string,
66 n: number
67): Promise<{ point: ResultPoint; uGrid: Float64Array }> {
68 const id = nextId++;
69 return new Promise((resolve, reject) => {
70 pending.set(id, { resolve: resolve as never, reject });
71 post({ type: "solution", id, instanceId, solverId, n });
72 });
73}