Skip to content

fix: keep GetSnapshotWithError supported, caller-owned checkpoints, reusable layout worker - #27

Merged
rendis merged 3 commits into
mainfrom
issue/wonderful-fermi-8r8eid
Oct 5, 2026
Merged

rendis merged 3 commits into
mainfrom
issue/wonderful-fermi-8r8eid

Conversation

@rendis

@rendis rendis commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

This PR fixes three problems that came from combining #25 and #26. All three should be fixed before the next release.

1. Keep GetSnapshotWithError supported (docs only)

ExQuantumMachine.GetSnapshotWithError was added during the current unreleased cycle (#22/#23). #25 deprecated it before any release shipped it.

  • experimental/machine.go: the Deprecated: notice is replaced by a note pointing to GetSnapshotContext for callers that need cancellable lock waiting or callback reentry detection.
  • docs/runtime.md, docs/instrumentation.md: these said "context-free snapshot methods are deprecated", which also covered GetSnapshotWithError. They now name only GetSnapshot and LoadSnapshot.
  • CHANGELOG.md: adds a Deprecated section, because Handle snapshot errors and run Studio layout in workers #25's deprecations were not recorded there.

2. Public history checkpoints stay caller-owned (Studio)

In #26, commit-snapshot took ownership of any snapshot returned by the public createHistorySnapshot, to skip a second clone. That breaks the contract #25 documented in docs/studio-performance.md: supplied checkpoints are mutable and caller-owned.

Reproduction on current main: create a snapshot, commit it, mutate snapshot.machineConfig.id, then undo. Undo restores the mutated value.

The fix:

Tests:

  • New test: a public checkpoint mutated after commit does not change what undo restores. It fails on main and passes here.
  • New test: the internal checkpoint is stored without a copy, and ownership transfers only once.

3. Reusable layout worker with a fallback (Studio)

In #25 every layout created, initialized and terminated a new ELK worker. Each layout spent 200–400 ms starting the 1.6 MB engine, so small graphs were slower end to end than on the main thread. And if the worker could not load (404, worker-src CSP, cross-origin asset URL), every layout failed and only logged a console.error.

  • Reuse. One worker per URL serves all layouts, concurrent ones included (elk-api tags each message with an id). It is released after 60 s idle.
  • Fallback. If the worker cannot start or load, the layout runs on the bundled engine on the main thread, and that URL is not retried for the rest of the page session. A worker that crashes after working is discarded; its in-flight requests fall back and the next layout starts a new worker.
  • Timeout. After 30 s the request still rejects and the worker is discarded. It does not fall back, because rerunning a stuck graph on the main thread would freeze the UI.
  • ELK errors. Errors from an invalid graph are returned unchanged and the worker is kept.

autoLayoutWorker.test.ts was rewritten with 10 tests. They cover worker reuse, falling back on error and messageerror, a throwing Worker constructor, a missing Worker global, a crash after success, timeout, ELK errors, and idle release.

Checked in Chromium against the real ELK worker served by the Vite dev server:

  • The initial layout plus three manual ones used a single worker, with no console errors.
  • With a broken worker URL, the editor tried it once, logged the fallback warning, and later layouts kept working.

Validation

  • Go: go build, go vet, go test ./...
  • Studio: lint, typecheck, test (330 + 3 tests), build, Stryker dry-run

claude added 2 commits October 5, 2026 15:55
GetSnapshotWithError was added in this unreleased cycle and deprecated again
before any release. Keep it as the supported checked capture method; only the
context-free GetSnapshot and LoadSnapshot stay deprecated. Name those two
explicitly in the docs and record the deprecations in the changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyRBcc1W1QuigZPCFx26zm
#26 let commit-snapshot take ownership of any snapshot returned by the public
createHistorySnapshot, to skip a second clone. That contradicts the contract
documented in docs/studio-performance.md (supplied checkpoints are mutable and
caller-owned): a consumer that mutated a checkpoint after committing it
silently changed what undo restored.

createHistorySnapshot is copied on commit again. Ownership transfer is now an
internal, non-exported mechanism used only for the editor's own drag/gesture
checkpoint, which is never exposed, so the editor keeps the single-clone gain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyRBcc1W1QuigZPCFx26zm
@rendis rendis changed the title docs(runtime): keep GetSnapshotWithError supported fix: keep GetSnapshotWithError supported and public history checkpoints caller-owned Oct 5, 2026
The worker path from #25 created, initialized, and terminated a new ELK worker
for every layout, so each layout paid 200-400 ms of engine startup and small
graphs were slower than on the main thread. If the worker could not load (404,
worker-src CSP, cross-origin asset URL), every layout failed with only a
console error.

- One worker per URL is reused, including for concurrent requests (elk-api
  tags each message with an id), and released after 60 s idle.
- If the worker cannot start or load, the request falls back to the bundled
  engine on the main thread and the URL is not retried this page session.
  A worker that crashes after succeeding is discarded and recreated next time.
- A 30 s timeout still rejects without falling back, discarding the worker,
  since rerunning a stuck graph on the main thread would freeze the UI.

Verified in Chromium against the real elk worker: initial plus three manual
layouts used a single worker with no errors; a broken worker URL was tried
once, fell back, and layouts kept working.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyRBcc1W1QuigZPCFx26zm
@rendis rendis changed the title fix: keep GetSnapshotWithError supported and public history checkpoints caller-owned fix: keep GetSnapshotWithError supported, caller-owned checkpoints, reusable layout worker Oct 5, 2026
@rendis
rendis merged commit 2ee0034 into main Oct 5, 2026
6 checks passed
@rendis
rendis deleted the issue/wonderful-fermi-8r8eid branch October 5, 2026 16:12
rendis added a commit that referenced this pull request Oct 5, 2026
fix: keep GetSnapshotWithError supported, caller-owned checkpoints, reusable layout worker
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants