1import type { BeadSystem, Excitation, SimOptions, SimResult } from './types';
3export interface Running {
4 promise: Promise<SimResult>;
5 cancel: () => void;
6}
8// Starts a solver worker (src/sim/worker.ts). The page loads it from its own file; the
9// embedded widget, which runs on other sites, has it inlined (a worker must be same-origin).
10export type MakeWorker = () => Worker;
12// onPartial gets the result so far every few seconds while the run is in progress
13export function runInWorker(
14 makeWorker: MakeWorker,
15 sys: BeadSystem,
16 exc: Excitation,
17 opt: SimOptions,
18 gpu: boolean,
19 onProgress: (f: number) => void,
20 onPartial?: (r: SimResult) => void,
21): Running {
22 const worker = makeWorker();
23 let reject!: (e: Error) => void;
24 const promise = new Promise<SimResult>((res, rej) => {
25 reject = rej;
26 worker.onmessage = (ev) => {
27 const m = ev.data;
28 if (m.type === 'progress') onProgress(m.fraction);
29 else if (m.type === 'partial') onPartial?.(m.result);
30 else if (m.type === 'done') {
31 worker.terminate();
32 res(m.result);
33 } else {
34 worker.terminate();
35 rej(new Error(m.message));
36 }
37 };
38 worker.onerror = (e) => {
39 worker.terminate();
40 rej(new Error(e.message));
41 };
42 });
43 worker.postMessage({ sys, exc, opt, gpu });
44 return {
45 promise,
46 cancel: () => {
47 worker.terminate();
48 reject(new Error('cancelled'));
49 },
50 };
51}