- put_in_batch (src/store/put.rs) opens with debug_assert!(Arc::ptr_eq)
on the Batch's registry Arc against the store's (new crate-internal
accessors Batch::registry / GcHome::core), before any pin is minted.
Chosen point recorded over a named error: the mis-use is
developer-error territory and the error family is ADR-pinned
(ADR-012 §6.5). Test drives the foreign batch against two stores
(should_panic).
- delete_everywhere (src/store/sweep.rs): the large-failure arm wraps
the underlying media failure in an Error::Io message naming both
homes' outcomes ("kv home deleted — the entry's homes diverged ..."
/ "kv home absent") — the wrapped report recorded over a payload
variant or report field; the kv-failure short-circuit arm propagates
unwrapped (nothing has moved). The self-healing re-mark posture is
unchanged; the observability is the fix. Test drives the
degenerate-duplicate shape (same key in both homes) through public
delete() with a large-home delete-failure injection, asserting the
report text and the real divergence (kv has == false, large has ==
true).
- Riding knob: LocalBackend gains a cfg(test) fail_delete injection
(inject_fail_delete), mirroring the engine knobs' pattern.
Verified: cargo test (default) — lib 134 + conformance columns green;
cargo test --all-features green against the live pglo-poc harness (4
binaries, pg columns ran for real); cargo clippy --all-targets
-- -D warnings green (default + all-features); cargo fmt --check clean.
6.2 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | ||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| smells-n5-n7 | N-5 + N-7 — put_in_batch's foreign-Batch assert; delete_everywhere's partial-failure reporting | completed | narrow | low | isolated | implementation |
|
Description
Two one-spot neighborhood smells from review-001 (the plan's §Wave 9 keeps them in the correctness round; they are too small for their own sessions but belong somewhere owned):
- N-5 —
put_in_batchaccepts a foreignBatch(src/store/put.rs:133): no identity check on the batch's registry Arc; cross-store use leaks pins into the other store's in-process registry (release is silently a no-op in the wrong one). The review's close: adebug_assert!(Arc::ptr_eq)on the batch's registry against the store's. A test drives the assert (debug builds run it); if the test round wants the refusal drivable in release too, a named error is the accepted alternative — the chosen point recorded. - N-7 —
delete_everywhereleaves the two homes divergent on partial failure (src/store/sweep.rs:761): kv deleted, large failed ⇒Errwith half the entry gone, unprotected (self-healing by the next sweep's re-mark — the mechanism stays; what's missing is observability). TheErrshould report which homes moved. The reporting shape is the task's design point (an error payload variant, a wrapped error, or a report field — recorded), chosen to not break the error family's altitude discipline (ADR-012 §6.5: operational errors stay honest without becoming diagnostics dumps). A test drives the partial-failure shape (large-tier failure injected; the kv home's deletion observable in the report).
No other behavior change: the self-healing re-mark posture is reviewed-correct and stays.
Acceptance Criteria
put_in_batchdebug-asserts the Batch's registry identity (or the named-error alternative); the chosen point recorded; a test drives the foreign-Batch casedelete_everywhere's partial failure reports which homes moved; the shape recorded; a test drives the kv-deleted/ large-failed divergence- No other behavior change; the error family's altitude discipline held
- Gates green:
cargo test(default),cargo test --all-featuresserver-less, clippy--all-targets -- -D warnings,cargo fmt --check
References
- docs/reviews/001-storage-surface-general-review.md (N-5, N-7)
- docs/plans/implementation.md (§Wave 9 — "the neighborhood smells")
- src/store/put.rs (
put_in_batch) - src/store/sweep.rs (
delete_everywhere; adjacent to F-1'sarbitrated_delete— land after tasks/f1-arbitrate-conclude.md if the diffs would tangle, otherwise order-free) - docs/architecture/decisions/012-pre-decomposition-consistency-rulings.md §6.5 (the error altitude discipline)
Notes
N-5 — chosen point: debug_assert!(Arc::ptr_eq) (the review's
close), not a named error. put_in_batch
(src/store/put.rs) opens with the identity check — the batch's
registry Arc against the store's (Batch::registry accessor vs
GcHome::core accessor, both crate-internal) — before any pin is
minted. Rationale recorded in the seam's doc comment: the mis-use is
developer-error territory, and the error family is ADR-pinned (ADR-012
§6.5 — new variants are new ADRs), so a named refusal would have been
a new ADR for a mis-use a debug tripwire catches in the round that
wants it (debug builds run the assert; release builds run on — the
assert's window exists to catch the leak, not to gate consumers). The
test (store::tests::put_in_batch_refuses_a_foreign_batch_in_debug_builds)
drives the foreign-Batch case against two mem_only stores with
#[should_panic(expected = "foreign Store")].
N-7 — chosen reporting shape: wrapped Error::Io carrying a
one-line homes report, not a payload variant and not a report field.
At the large-failure arm the underlying media failure is re-raised as
Error::Io(format!("delete partial failure: large home delete failed ({err}); {homes}")), where homes is "kv home deleted — the entry's
homes diverged (residue; the next sweep's re-mark reconciles)" or "kv
home absent (nothing moved there)" — which homes moved, plus the
failure cause, verbatim the ADR-012 §6.5 honesty without a diagnostics
dump. The kv-failure short-circuit arm propagates unwrapped (nothing
has moved yet — no divergence to report). No variant added; the family
stays ADR-pinned. The self-healing re-mark posture is unchanged — the
observability is the fix. The test
(store::tests::delete_everywhere_partial_failure_reports_which_homes_moved)
builds the degenerate-duplicate shape (the same key planted in both
homes by hand — the only shape where kv-deleted + large-failed can
diverge), drives it through public delete() with a large-home
delete-failure injection, and asserts the report names the failed
home, the kv move, and the injected cause, plus the real
divergence: kv has false, large has true.
Riding change (no behavior change): LocalBackend gained a
fail_delete cfg(test) injection knob (mirroring the engine knobs'
pattern — inject_fail_delete), to drive the large-tier media failure
the filesystem cannot reliably produce in tests.
Summary
Both neighborhood smells closed with their tests. N-5:
put_in_batch now debug-asserts the Batch's registry identity
(Arc::ptr_eq, accessors Batch::registry/GcHome::core) before
any pin is minted — the debug-assert point recorded over the named
error (family is ADR-pinned, ADR-012 §6.5); test drives the foreign
batch against two stores. N-7: delete_everywhere's large-failure arm
wraps the media failure in an Error::Io message that reports which
homes moved (kv deleted / kv absent vs large failed) — the wrapped
shape recorded over a payload variant or report field; test drives
the kv-deleted/large-failed divergence through public delete() and
pins both has observables. No other behavior change; the re-mark
self-healing posture stays. Gates: cargo test (default) green,
cargo test --all-features green against the live pglo-poc harness
(the pg columns ran for real), both cargo clippy --all-targets -- -D warnings runs green (default + all-features), cargo fmt --check
clean.