docs(architecture): ADR-008 — trait size probe, fleet GC, fs-tier engines; requirements anchor
- requirements.md (new): the three use cases pinned as REQ-1..4 with the node/pool/fleet/engine vocabulary defined once — ends per-session re-derivation of consumer facts. REQ-2 (replicator fleet over one shared pg pool, incl. large-blob serving) is recorded as a planning fact predating all POCs, on the operator's authority. - ADR-008: Backend trait gains size(key) length probe (before any backend ships data — ADR-002 one-way-door discipline); fleet GC mechanism (DB-backed pin rows committed atomically with entries, TTL+renewal semantics, liveness = embedder-owned table, protect callback is single-node-only, advisory-locked single sweeper, staged re-arbitrated delete window on both engines); fs tier becomes engine-selectable (local default; pg-lo named candidate) with the fleet locality contract (shared media or re-routing; mixed tiers are a documented deployment invariant, not a constructor-provable one). - poc-pglo-spec.md (new): POC #7 spec — pg Large Objects as the fs tier's pg-lo engine; instruments, decision gate, registered in phase-0.md OQ-BL-06. - ADR-003/005 status amendments point to ADR-008's extensions; specs ripple (backends/store-api/gc/ops/overview/README). - open-questions.md: deferral-policy header gains the decisions-vs- sequenced-work distinction; pg-lo's why-not-parked audit trail recorded. - research fixes: postgres POC renumbered #4->#5 to the canonical register (phase-0 OQ-BL-06), redb cross-refs fixed, thinking- artifact sentence in B1 replaced with the honest reading. Verification: docs-only change; reference-integrity sweep across the tree (ADR/REQ/POC refs resolve); architecture-reviewer pass on the delta — original 3 criticals addressed, its follow-up (fleet liveness form, pin TTL, staged-delete semantics, enforceability, shared-media caveats) fixed in this commit.
This commit is contained in:
1 parent
395d58cf3f
commit
281c37876e
16 files changed
+689
-88
No files matched your search
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-02
|
||||
last_updated: 2026-10-03
|
||||
---
|
||||
|
||||
# Backends and dispatch
|
||||
@@ -39,10 +39,16 @@ is ever reachable through that door.
|
||||
is also the persistence boundary — a kv row or an fs filename has no
|
||||
schema-migration story, so the byte layout must be self-describing
|
||||
(algorithm-tagged keys).
|
||||
- **Methods:** `has` / `get` / `put` / `delete` / `list` / `name`.
|
||||
Streaming put/get shapes ride the store layer's seams (store-api.md);
|
||||
- **Methods:** `has` / `get` / `put` / `delete` / `list` / `name` /
|
||||
`size` (the length probe added by ADR-008). Streaming put/get shapes
|
||||
ride the store layer's seams (store-api.md);
|
||||
backends provide byte- or handle-level primitives underneath
|
||||
(`get` on the fs tier yields a file handle, not a loaded buffer).
|
||||
`size(key)` returns the entry's length or `None` if absent —
|
||||
metadata only, never a content fetch: kv engines probe the indexed
|
||||
`size` column both row shapes carry (POC #5 B5); the `local` fs
|
||||
engine stats the file. Store-level `stat` and pool accounting ride
|
||||
this method.
|
||||
- **`list()` complete by contract.** A *malformed* list is as deadly as
|
||||
an incomplete one: list correctness is only observable through GC
|
||||
(POC #1 finding 2 — the redb key-vs-value trap produced a sweep that
|
||||
@@ -122,18 +128,43 @@ sweep-outcome CI gate, run against dockerized postgres under
|
||||
near-linearly to ~37k puts/s at 24 conns — the only engine whose
|
||||
throughput *increases* under concurrency.
|
||||
|
||||
### fs backend (feature `fs`, default-on)
|
||||
### fs backend (feature `fs`, default-on); engines: `local` (default) + `pg-lo` (candidate)
|
||||
|
||||
Large blobs. Flat sharded layout: `{hex-prefix}/{hex-prefix}/{hash}`
|
||||
sharding survives from iroh's conclusion (limits directory size on
|
||||
huge pools); stage-then-commit-rename for the two-pass unknown-length
|
||||
path; pread-based range reads (POC #3 finding A2 — local range serving
|
||||
is sound, e.g. for packfiles).
|
||||
Large blobs. Like the kv tier (ADR-007), the fs tier is **one contract,
|
||||
multiple engines** — the medium is a per-node constructor choice
|
||||
(ADR-008; REQ-2 in requirements.md makes the engine concept load-bearing
|
||||
for fleets):
|
||||
|
||||
- **`local` engine** (the default; the ADR-003 backend as originally
|
||||
specced): flat sharded layout:
|
||||
`{hex-prefix}/{hex-prefix}/{hash}` sharding survives from iroh's
|
||||
conclusion (limits directory size on huge pools); stage-then-commit-
|
||||
rename for the two-pass unknown-length path; pread-based range
|
||||
reads (POC #3 finding A2 — local range serving is sound, e.g. for
|
||||
packfiles).
|
||||
- **`pg-lo` engine** (candidate, *not shipped*; ADR-008): postgres
|
||||
Large Objects as the fs tier's storage — the same engine-behind-
|
||||
one-trait move as ADR-007, one tier over. Admission is gated on
|
||||
POC #7's measured evidence and its own engine ADR (see
|
||||
`docs/research/poc-pglo-spec.md`).
|
||||
- **Fleet locality contract (ADR-008):** over one shared pool, the fs
|
||||
tier is either shared media (every node's `local` root on the same
|
||||
fleet-shared media — soundness caveats and the required media
|
||||
guarantees in ADR-008) or re-routed (one storage node serves pool
|
||||
large-blob content via the ops surface; client nodes are
|
||||
kv-tier-only over pool content). Mixed per-node-local fs tiers over
|
||||
one pool is the partitioning failure this contract exists to
|
||||
prevent — a documented deployment invariant the constructor cannot
|
||||
fully prove but must be declared against (ADR-008 names the
|
||||
enforceable seam and the detection symptom).
|
||||
|
||||
### mem backend (feature `mem`, default-off)
|
||||
|
||||
`BTreeMap`-shaped ephemeral backend for tests and in-process
|
||||
ephemerality. A testing/utility tier, never a production story.
|
||||
Implements the full trait contract including `size` (trivially) — it
|
||||
exists partly as the reference impl every other backend's conformance
|
||||
tests can mirror.
|
||||
|
||||
## Size-threshold dispatch (ADR-003)
|
||||
|
||||
@@ -156,12 +187,13 @@ ephemerality. A testing/utility tier, never a production story.
|
||||
The trait is open to future implementations (network stores, S3-like
|
||||
tiers), but nothing in the current consumer set requires one, and the
|
||||
contract is deliberately hostile to half-implementations (complete
|
||||
`list()`, GC-participating `delete`). Any future backend — or third kv
|
||||
engine — is a new ADR carrying its own sweep-safety story (ADR-007 is
|
||||
the precedent for an engine addition: measured evidence first, impl
|
||||
contract naming the durability/ops posture deltas). This crate's
|
||||
roadmap is not blocked on one (see open-questions.md — alkfs intake
|
||||
may name needs externally; OQ-08).
|
||||
`list()`, GC-participating `delete`). Any future backend — or a third
|
||||
kv engine or second fs engine — is a new ADR carrying its own
|
||||
sweep-safety story (ADR-007 is the precedent for a kv engine
|
||||
addition; ADR-008 named pg-lo as the candidate second fs engine with
|
||||
POC #7 as its admission evidence — the door is exercised twice). This
|
||||
crate's roadmap is not blocked on one (see open-questions.md — alkfs
|
||||
intake may name needs externally; OQ-08).
|
||||
|
||||
## Design Decisions
|
||||
|
||||
@@ -171,6 +203,7 @@ may name needs externally; OQ-08).
|
||||
| [004](decisions/004-two-backends-no-third.md) | Two backends, no third | scope boundary against manifest-layer absorption |
|
||||
| [005](decisions/005-pooled-cas-and-gc-mechanism.md) | Namespace-blindness | backends see hashes only |
|
||||
| [007](decisions/007-two-kv-engines-sqlite-and-postgres.md) | Two kv engines | sqlite (default) + postgres behind one trait; one relational engine + fs per node |
|
||||
| [008](decisions/008-trait-size-probe-fleet-gc-and-fs-engines.md) | `size` probe + fleet GC + fs engines | trait length probe; DB-backed pins/advisory-locked sweeper for fleets; fs tier engine-selectable (`local` default, pg-lo candidate) |
|
||||
|
||||
## Open Questions
|
||||
|
||||
|
||||
Reference in new issue
Block a user