/ concept-collection / hitandrun-commonview
Sign in
concept-collection / hitandrun-commonview
hitandrun-commonview / README.md
68 lines · 3.5 KBCodeBlameHistory
40dabfdInitial commit: shared-view hit-and-run samplerJeremy Magland 1# hitandrun-commonview
3One interactive figure, one shared view. This app shows the
4[hitandrun-interactive](https://github.com/concept-collection/hitandrun-interactive)
5hit-and-run sampling figure — just the figure, no source code — and keeps it
6**identical for everyone who has the page open**, in the style of
7[commonview](https://github.com/concept-collection/commonview): peers discover
8each other over nostr relays and form a WebRTC full mesh; the oldest peer is
9the **central** peer and owns the authoritative state.
11The twist over commonview's counter: the shared state is a live MATLAB
12computation. The central peer — and only the central peer — runs
13[numbl](https://numbl.org) (a MATLAB-compatible runtime) in a web worker,
14executing the *unmodified* `hitandrun_demo.m` from hitandrun-interactive. The
15figure's uihtml bridge is intercepted host-side (no iframe): control changes
16from **any** viewer are forwarded to the central peer, which feeds them to the
17script and broadcasts the results — parameter selections, the region, and the
18samples — to every viewer.
20## What is shared
22- **Parameters**: sample count, convex/non-convex region, local-segment mode.
23- **The region and the samples**: samples travel as a Float32 blob (up to
24 100,000 points ≈ 800 KB), streamed in 64 KB chunks over the data channel and
25 authenticated by a SHA-256 in a signed header. The JSON "view" message that
26 follows it references the blob by id.
27- **The sampling movie**: the central peer drives the animation clock, so every
28 viewer watches the same step at the same time.
30## Graceful failover
32- Every message is a signed envelope (schnorr over the peer's key, which *is*
33 its ID); state is only trusted from the current central peer.
34- Every peer keeps the latest sample blob, so whichever peer becomes central
35 can serve it to late joiners.
36- If the **central peer leaves**, the next-oldest peer becomes central, boots
37 its own engine (viewers see "starting engine…"), and continues from the
38 last-known state — the script is stateless (the region rides along with each
39 resample request), so any peer's engine can pick up where the last one left
40 off.
41- If the central peer's **engine fails to boot or to compute** (a timeout
42 counts), it announces the failure and steps down; the election skips
43 engine-failed peers, and the next-oldest healthy peer takes over.
44- State is never persisted: once all peers leave, the room resets.
46## Run
48```
49npm install # requires numbl >= 0.4.8 on npm (browser-embedding exports)
50npm run dev
51```
4711a6cGenerate peer identity per page loadJeremy Magland 53Open the printed URL in two tabs (identity is per page load, so every tab is
54its own peer). Drag the samples slider or press "New region" in either window
55and watch both update; close the central window and watch the other take over.
57## How the engine embedding works
59`src/engine/numbl.worker.ts` runs `executeCode` from the `numbl` npm package
60against an in-memory filesystem holding the `.m` files (verbatim copies from
61hitandrun-interactive, under [matlab/](matlab/)). The script's
62`uihtml(...)` call surfaces as a plot instruction carrying the component id and
63initial Data; `sendEventToHTMLSource` calls surface via the `onHtmlSourceEvent`
64hook; and events from the app re-enter the still-live interpreter through the
65`UihtmlSession` returned by `executeCode` — firing the script's
66`HTMLEventReceivedFcn` exactly as if the figure page had sent them. The HTML
67the script loads for the figure is replaced by a one-line placeholder; nothing
68is ever rendered from the worker.
moveopenescclose