Files
alkblobs/tasks/store-put-paths.md
T
glm-5.3-flash 6bce301c55 docs(tasks): decompose wave 2 — mem + local engines, facade, in-process GC, first suite columns
Nine tasks against the wave-1 contract surface as reviewed (no
amendments from the gate):

- engine-mem / engine-local (parallel, dependency-free): the two
  engines; local owns the stage-hygiene exact-count tests and the
  Drop-cancellation story the wave-1 review recorded
- store-construction: the Store type, constructor modes, size-threshold
  dispatch; binds the conformance factory's Store associated type
- store-read-paths ∥ gc-protocol: read ops with the ADR-012 §6.1
  fall-through rule; the ADR-005 in-process protocol (pins, liveness,
  delete windows, abort-as-data, GcRefuse with the full protection set)
- store-put-paths: the two put paths behind one signature, ADR-003's
  three numbered rules, pin-before-publish, Batch, kv-only rejection
- suite-column-mem → suite-column-local: the reference column, then the
  dual-tier dispatch-coverage shape mirroring it
- review-wave-2: the gate (facade/dispatch/GC vs ADR-003/005/012)

Verification: dependency graph validated (all ids resolve, no cycles,
topological order clean); docs-only change.

Refs: docs/plans/implementation.md §Wave 2
2026-10-11 21:39:28 +00:00

5.1 KiB

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
store-put-paths Store put seam — two internal paths, the three numbered rules, Batch, kv-only rejection pending
gc-protocol
moderate medium component implementation
wave-2
facade
write-path

Description

Implement the facade's put seam on the Store type (store-api.md §Write path): put(len: Option<u64>, stream) → (Key, Pin) — two internal paths behind one signature, with pin-before-publish from the gc-protocol registry.

  • Known-length path (encouraged, documented as such on the API): the preamble ("blob <len>\0") is known before content flows, so the hash initializes with it and one pass suffices — no staging needed for hashing. Routing by the dispatch seam: ≤ threshold → the kv tier's whole-value put; > threshold → the large tier's staged put (content streams into the staging cursor while hashing; the derivation completes at stream end; commit-rename publishes).
  • Unknown-length path: content buffers in memory up to the dispatch threshold. ADR-003's three numbered rules (option (d)), each a test-asserted behavior:
    1. Threshold exceeded mid-stream (non-restartable sources are normal): the buffered prefix flushes into a fresh stage file and the stream continues appending into it — there is no "restart the stream" requirement anywhere.
    2. Verification runs over the eventual stored artifact as a whole: the memory buffer for the sub-threshold kv commit; the complete staged bytes for the large commit — the derivation pass restarts over preamble + staged bytes (forced by the preamble being inside the hashed input, ADR-002), reading the staged artifact back through the StagingCursor: ReadCursor seam (the wave-1 design-led extension). There is no stitched-input case left ambiguous.
    3. Stream error before commit: no entry lands and no stage file remains — buffer discard on the failure path, exactly like stage discard (the stage-hygiene invariant extends to the buffered case).
  • Pin-before-publish (ADR-005): the pin refcount is acquired under the arbitration lock before the entry becomes visible — publish and protection are one step; an entry cannot appear in a sweep's list() without already carrying its pin.
  • Dedup: a re-put of existing content acquires no new pool entry — the returned Pin refcounts the existing one under the same lock.
  • Batch (store-api.md §Write path): the batching put seam — multi-put writes group under one batch-scoped pin; member puts publish pin-before-publish exactly as lone puts do; the batch's pins drop together on commit or drop (the gc-protocol machinery drives).
  • kv-only mode rejection (ADR-012 §6.2): known-length puts exceeding the threshold reject immediately; unknown-length puts reject at mid-stream threshold overflow — lengths are not known at construction, so put time is the only possible rejection point. Zero residue on either rejection.
  • Named design points: (a) the stream parameter shape (impl AsyncRead + Unpin + Send vs a boxed trait object — the family's no-dyn posture vs ergonomics); (b) the declared-len mismatch case (a known-length stream that yields fewer/more bytes than len — which error family member carries it, and zero residue either way). Record both for the review gate.

Acceptance Criteria

  • put(len, stream) → (Key, Pin) with both internal paths behind the one signature; routing is the pure length function (no content ever migrates tiers)
  • The three numbered rules each behavior-tested: mid-stream overflow flushes into a fresh stage and the stream continues; the derivation pass runs over the eventual stored artifact as a whole (buffer form and staged-bytes form); stream error leaves no entry and no stage file
  • Pin-before-publish holds on both paths and both tiers; dedup re-puts refcount the existing entry
  • Batch groups multi-put writes; member pins drop together
  • kv-only mode: known-length over-threshold rejects immediately; unknown-length rejects at mid-stream overflow; zero residue on both
  • Stream-shape and len-mismatch design points decided and recorded
  • cargo test green; cargo test --features mem and cargo test --all-features green; clippy/fmt gates green

References

  • docs/architecture/store-api.md (§Write path — the put seam, stage hygiene invariant)
  • docs/architecture/decisions/003-backend-contract-and-dispatch.md (§Dispatch policy — the three numbered rules, option (d))
  • docs/architecture/decisions/012-pre-decomposition-consistency-rulings.md §6.2 (kv-only put-time rejection)
  • docs/architecture/decisions/005-pooled-cas-and-gc-mechanism.md (pin-before-publish, dedup refcount)
  • docs/architecture/decisions/010-backend-io-seams-and-fleet-state-home.md §1 (the staged-put contract)
  • src/backend.rs (StagingCursor: ReadCursor — the verification-pass seam)

Notes

To be filled by implementation agent

Summary

To be filled on completion