/// import type { PlanningOutcome } from './leave-planner.service'; import type { WorkerRequest, WorkerResponse } from './leave-planner.worker-messages'; import { analyzeCounterfactualInternal, calculatePlanningAsyncInternal, explainIncompleteCheckpoint, type PlanningArtifacts, } from './leave-planner.core'; const worker = self as DedicatedWorkerGlobalScope; let activeCalculation: { cancelled: boolean } | undefined; worker.onmessage = async (event: MessageEvent) => { try { if (event.data?.type === 'cancel') { if (activeCalculation) activeCalculation.cancelled = true; return; } if (event.data?.type === 'plan') { const calculation = { cancelled: false }; activeCalculation = calculation; let artifacts: PlanningArtifacts = {}; let outcomePosted = false; let outcome: PlanningOutcome; // The cooperative driver yields during preparation and search, even within one phase. const heartbeat = () => worker.postMessage({ type: 'heartbeat' } satisfies WorkerResponse); const heartbeatTimer = setInterval(heartbeat, 1000); try { heartbeat(); outcome = await calculatePlanningAsyncInternal( { ...event.data.request, progress: (stage: string) => worker.postMessage({ type: 'progress', stage, } satisfies WorkerResponse), }, (plan, state) => worker.postMessage({ type: 'checkpoint', plan, state, } satisfies WorkerResponse), (value) => (artifacts = value), (value) => { outcomePosted = true; worker.postMessage({ type: 'result', outcome: value, } satisfies WorkerResponse); }, (explanation, explanationError, finalState) => worker.postMessage({ type: 'explanation', explanation, explanationError, finalState, } satisfies WorkerResponse), () => calculation.cancelled, ); } catch (error) { worker.postMessage({ type: 'error', code: 'planner-error', message: error instanceof Error ? error.message : String(error), } satisfies WorkerResponse); return; } finally { clearInterval(heartbeatTimer); if (activeCalculation === calculation) activeCalculation = undefined; } if (!outcomePosted) worker.postMessage({ type: 'result', outcome } satisfies WorkerResponse); worker.postMessage({ type: 'artifacts', artifacts } satisfies WorkerResponse); return; } if (event.data?.type === 'explain-checkpoint') { const result = explainIncompleteCheckpoint( event.data.request, event.data.plan, event.data.state, event.data.interruption, ); worker.postMessage({ type: 'explanation', ...result } satisfies WorkerResponse); return; } if (event.data?.type !== 'counterfactual') return; try { const analysis = analyzeCounterfactualInternal( event.data.request, event.data.plan, event.data.placement, event.data.state, ); worker.postMessage({ type: 'counterfactual-result', analysis, } satisfies WorkerResponse); } catch (error) { worker.postMessage({ type: 'error', code: 'counterfactual-error', message: error instanceof Error ? error.message : String(error), } satisfies WorkerResponse); } } catch (error) { worker.postMessage({ type: 'error', code: 'worker-error', message: error instanceof Error ? error.message : String(error), } satisfies WorkerResponse); } };