Amp-Thread-ID: https://ampcode.com/threads/T-019f9d91-77c1-7206-a60f-ed6554ce92ab Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
2.0 KiB
Live composition
What you will build
An editor that replaces a version-1 node definition with version 2 and migrates its graph instance atomically.
Prerequisites and checkpoint
Understand composition. Start with the v1 node visible and retain the receipt's revision.
1. Acquire the v1 revision
import type { FxNode, FxNodeView } from "fxnode";
const v1Receipt = await api.composeNode("example.live.parameter", liveNodeV1);
let revision = v1Receipt.revision;
This is an excerpt: await socket dependencies first, compose v1, call setState, attach a view, add its instance through that view, attach the host, and render. Checkpoint: v1 is visible and revision came from its receipt—not a guessed constant.
2. Replace it using the v2 receipt
async function upgrade(root: FxNode, view: FxNodeView) {
const v2Receipt = await root.composeNode("example.live.parameter", liveNodeV2, {
expectedRevision: revision,
});
revision = v2Receipt.revision;
await view.whenRendered();
return v2Receipt;
}
Invoke this on an explicit host action. Checkpoint: inspect v2Receipt.status, graphChanged, graphVersion, and updated revision; the migrated v2 node is visible. Clean up the button/page listeners, host, and API on teardown.
Why?
Composition revision and graph version are separate concurrency domains. A committed rebind can advance both; a no-op advances neither. Compare-and-swap prevents two writers from assuming the same authority.
Complete example
See the working examples/live-composition/main.ts and its definitions.
Related concepts / relevant API / next
Read graph state and events and CompositionReceipt, then plan lifecycle cleanup.