Expand description
Tier abstraction layer (Phase 14.6 — DS-14-storage Audit 4 + Q5 + Q8 locks, M4.B 2026-05-10).
Three-layer tier model (matching packages/pure-ts/src/extra/storage/tiers.ts):
- Layer 1 —
StorageBackend: generic bytes-level kv I/O. - Layer 2 — tier specializations parametric over
T:SnapshotStorageTier<T>— one record persave(snapshot)call.AppendLogStorageTier<T>— sequential entries with optional partitioning viakey_of.KvStorageTier<T>— many records, addressable by string key.
- Layer 3 — high-level wiring (
Graph::attach_storage, M4.E integration).
All sub-traits inherit BaseStorageTier, which carries the cadence
knobs (debounce_ms, compact_every), transaction lifecycle (flush,
rollback), and the dyn-safe bytes-level
BaseStorageTier::list_by_prefix_bytes enumeration. Typed enumeration
(decoding via the tier’s codec) lives on the typed sub-traits as free
functions or default-impl helpers.
§Sync, NOT async (D143)
Every method returns directly (no Future). Memory / redb / std::fs
backends are all sync-compatible; tokio-backed networking backends wrap
their async surface at the adapter layer (e.g. tokio::Handle::block_on).
See crate::backend module doc.
§debounce_ms semantics at M4.B (D144 — option (b))
The accessor BaseStorageTier::debounce_ms returns the configured
window. The tier itself does NOT drive a timer. The Graph layer
consumes this value at attach time (M4.E) and schedules flush() via its
own reactive timer source (from_timer / from_cron). Until then,
save always buffers and flush always commits — debounce has no
automatic effect.
Structs§
- Append
Cursor - D269 — Opaque cursor for windowed
load_entriespagination (memo:Re loadEntries-pagination parity). Mirrors TSAppendCursor.positionis a forward-only offset into the flattened, lex-ASC-by- key, entry-order-within-key sequence.tagis reserved for future stable-iteration tokens; currently alwaysNone. - Append
Load Result - D269 — Result of a paginated
AppendLogStorageTier::load_entries.cursor.is_none()⇒ no more entries (consumer should stop). Returning the whole tail withcursor.is_none()matches the back-compat shape (bareload_entries(LoadEntriesOpts::default())is byte-for-byte the pre-D269 behavior). - Load
Entries Opts - D269 — Options for
AppendLogStorageTier::load_entries.
Enums§
- Append
LogMode - D269 — Persistence mode (memo:Re P1 parity). Mirrors TS
AppendLogStorageOptions.mode.Append(default) reads existing bucket bytes, decodes, merges new entries, encodes, writes back — the M4.B behavior.Overwriteskips the read/merge entirely and snapshots the current batch as the bucket’s full contents. Used for callers that ship full snapshots per wave (e.g. WAL replay drivers) rather than deltas. Feeding deltas into anOverwritetier silently truncates the log to the last batch —attach_storagerejects overwrite sinks at attachment time.
Traits§
- Append
LogStorage Tier - Append-log tier — bulk-friendly entry persistence with optional
partitioning via
key_of. Mirrors TSAppendLogStorageTier<T>. - Base
Storage Tier - Common tier surface — cadence knobs + transaction lifecycle + bytes-level enumeration.
- KvStorage
Tier - Key-value tier — typed records under arbitrary string keys with codec
serialization at the storage boundary. Mirrors TS
KvStorageTier<T>. - Snapshot
Storage Tier - Snapshot tier — writes a single record per
save(snapshot)call. Mirrors TSSnapshotStorageTier<T>.
Type Aliases§
- List
ByPrefix Iter - Boxed lazy iterator yielded by
BaseStorageTier::list_by_prefix_bytes. Each item is either a(key, bytes)entry decoded from the backend or a surfacedStorageError(e.g. on first-yield if the backend doesn’t support enumeration — lazy-throw semantics from the TS impl).