Spaces:
Running
Running
| // Poll the local daemon for real wire events. Offline-tolerant by design: | |
| // the sim is fully alive without a daemon, so failures are silent and the | |
| // poll backs off until the daemon answers again. | |
| import { isWireEvent, type WireEvent } from "../engine"; | |
| const POLL_MS = 3000; | |
| const OFFLINE_BACKOFF_MS = 15000; | |
| export function startDaemonPoll(onEvents: (events: WireEvent[]) => void): () => void { | |
| let timer: ReturnType<typeof setTimeout> | undefined; | |
| let stopped = false; | |
| const tick = async () => { | |
| if (stopped) return; // unmounted before first tick — never drain for a dead poller | |
| let delay = POLL_MS; | |
| try { | |
| const res = await fetch("/api/events/pending", { signal: AbortSignal.timeout(2000) }); | |
| if (res.ok) { | |
| const body: unknown = await res.json(); | |
| const list = (body as { events?: unknown[] }).events ?? []; | |
| const valid = list.filter(isWireEvent); | |
| // a malformed event on this path means the daemon let contract drift through — be loud | |
| if (valid.length !== list.length) | |
| console.error("puck: daemon sent events violating the wire schema", list); | |
| // drain is destructive — a stopped poller (StrictMode's first mount) must not | |
| // swallow events meant for the live one. Losing one drain to an unlucky unmount | |
| // race is acceptable; silently eating every event on dev double-mount is not. | |
| if (valid.length && !stopped) onEvents(valid); | |
| } else { | |
| delay = OFFLINE_BACKOFF_MS; | |
| } | |
| } catch { | |
| delay = OFFLINE_BACKOFF_MS; // daemon not running — normal in Space/demo mode | |
| } | |
| if (!stopped) timer = setTimeout(tick, delay); | |
| }; | |
| // drain is destructive, so the first fetch must not race React StrictMode's | |
| // mount→unmount→mount: the doomed first instance is cleaned up synchronously, | |
| // well inside this delay, so only the surviving poller ever touches the queue. | |
| timer = setTimeout(tick, 350); | |
| return () => { | |
| stopped = true; | |
| clearTimeout(timer); | |
| }; | |
| } | |