pub fn attach_snapshot_storage(
core: &Core,
graph: &Graph,
pairs: Vec<AttachTierPair>,
options: AttachOptions,
) -> StorageHandleExpand description
Wire an observe subscription on graph that persists node changes
to the provided snapshot+WAL tier pairs.
§Debounce (D171, resolved 2026-05-14)
When a tier’s debounce_ms is Some(ms) with ms > 0, the
observe callback writes via the tier’s save() (which buffers
internally per the BaseStorageTier
contract) but does NOT force a flush(). Callers drain pending
writes by invoking StorageHandle::flush_all — typically from a
binding-side reactive timer (e.g.,
graphrefly_operators::temporal::interval). This keeps
graphrefly-storage sync + binding-agnostic per the canonical
no-async-in-storage invariant; reactive-timer wiring lives in the
layer that already owns the timer primitive.
When debounce_ms is None or Some(0), the observe callback
continues to force-flush inline as before.
§key_of (D174, closes F8)
The snapshot tier’s backend key is derived from graph.name via
the checkpoint record’s name field. Cross-impl key_of divergence
disappears at this boundary.
D246: the embedder owns the Core (see
graphrefly_core::OwnedCore) and passes &Core in — the
observe_all_reactive subscription is opened owner-side. Teardown
is owner-invoked via StorageHandle::detach (no RAII Drop,
D246 r3).