Files
alkblobs/tests/conformance/sqlite_column.rs
T
glm-5.3-flash 3f8e8158a7 feat(tests): the conformance suite's sqlite column — the durable-schedule SQL-backed column green (wave 3)
- The first SQL-backed column: the default-build production shape
  (kv = sqlite + large = local, feature sqlite default-on) runs the
  form-independent reference rows verbatim (INV-1, INV-6, the
  NoLivenessSources/ProtectFailed abort shapes, the kv-only rejection
  row against kv-only(sqlite)) and grows the durable-schedule sweep
  rows — exact counts asserted relative to the staged schedule
  (ADR-012 §6.7): two-sweep counts over the full protection set, the
  race across the window delay (a re-put landing during the window
  survives the executing sweep), the holder-stages-only lease shape,
  INV-5 through durable-schedule outcomes, and the schedule-relative
  INV-2/INV-3 readings
- Dispatch rows mirror the local column's family with the placement
  oracle adapted by medium: the sqlite file's pool/window rows vs the
  root's committed files; virgin-store reads as no-ops on a fresh file
  (the no-tables-yet tolerance engine-instrumented, this row its
  facade form)
- Factories: dual-tier sqlite+local and kv-only(sqlite), instance-
  tracked temp sites (fresh sqlite file + private root per open;
  idempotent panicking-row-safe teardown), the column-tuned threshold
  and the test window-delay tuning (Duration::ZERO — execute-on-next-
  sweep); the module is cfg(feature = "sqlite"), default-on — the
  column runs in every default cargo test, server-less, never skips
- Shared fixtures moved to rows.rs (committed_file_count,
  staging_file_count, slice_digest, LatchProtect pub(crate)) so the
  columns share them without the mem gate
- README: the schedule-relative reading for SQL-backed columns
  recorded (citing ADR-012 §6.7), the sqlite rows table inventory,
  Current state (three columns)

Verification: cargo test (default) green — 69 lib + 19 conformance +
3 git-interop; cargo test --features mem green (124 lib + 54
conformance); cargo check --all-features --tests green; cargo clippy
--all-targets -- -D warnings green; cargo fmt --check green.
2026-10-12 05:14:58 +00:00

1798 lines
67 KiB
Rust

//! The **sqlite column** — the suite's first SQL-backed column: the
//! reference row set run against the default-build production shape
//! (`kv = sqlite` + `large = local`; feature `sqlite` is default-on,
//! ADR-007, ADR-013 §4), extended with the **durable-schedule sweep
//! rows** and the dispatch rows (README §Columns beyond the reference
//! set; INV-7: every engine's rows mirror the reference column).
//!
//! The sweep rows are **schedule-relative on this column** (the
//! README §The schedule-relative reading for SQL-backed columns is
//! the recorded amendment, citing ADR-012 §6.7): the reference set's
//! single-sweep exact-count rows are the inline-form host's — the
//! durable form stages its candidates this sweep and executes them by
//! the next, so the exact counts here are asserted against the staged
//! schedule. The form-independent rows mirror verbatim
//! ([`crate::rows`]: the round-trip family, the stat-discipline row,
//! the no-sources and failed-protect abort shapes, and the kv-only
//! rejection row against the kv-only factory); the schedule-relative
//! properties grew their own rows below (dedup and stage hygiene
//! observe their invariants through sweep outcomes, so they read
//! against the schedule too). Mem-only never mirrors here: the mode
//! is not constructible without mem.
//!
//! The factories (README §The factory contract): `open()` vends the
//! concrete [`alkblobs::Store`] facade over a fresh temp site per
//! call — a private temporary directory holding the sqlite pool file
//! and the large engine's private root — so two opens never share
//! state. Teardown removes every site this factory instance vended
//! (idempotent: a repeated teardown is a no-op and an already-removed
//! directory is tolerated; safe against abandoned instances — each
//! site is private to its open). The local column's instance-tracks-
//! its-own-root pattern: every runner constructs its own factory, so
//! concurrent rows never touch each other's sites. The column never
//! skips (README §SKIP posture — server-less engines' columns must
//! always be green in every environment).
//!
//! The dual-tier dispatch rows mirror the local column's family with
//! the placement oracle adapted: both tiers are on disk now — kv
//! entries live in the sqlite file (the oracle counts its pool rows),
//! large entries under the local root — so the oracle distinguishes
//! by medium.
#![allow(dead_code)]
use std::io::Cursor;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use rusqlite::Connection;
use crate::factory::StoreFactory;
use crate::rows::{
self, committed_file_count, patterned, slice_digest, staging_file_count, Failing, LatchProtect,
SetProtect, SetSource,
};
use alkblobs::{Error, Key, Store, StoreMode, DEFAULT_DISPATCH_THRESHOLD};
// ------------------------------------------------------------------
// The factories
// ------------------------------------------------------------------
/// The column's declared dual-tier threshold — small, so the shared
/// content matrix and the race fixtures cross it and both tiers'
/// bodies are exercised (sub-threshold rows land in the sqlite file;
/// over-threshold rows stage-commit into the local root).
pub(crate) const TUNED_THRESHOLD: u64 = 1024;
/// The column's declared kv-only rejection threshold — small, so every
/// leg of the rejection row stays trivially materializable.
pub(crate) const KV_ONLY_THRESHOLD: u64 = 1024;
/// The **test tuning of the window delay** (ADR-008 §2's legal
/// degenerate tuning): `0` — execute-on-next-sweep. The durable
/// schedule's staging sweep stages the dead set; the *next* sweep is
/// its executor, which is exactly the schedule the sweep rows assert
/// against.
pub(crate) const WINDOW_DELAY: Duration = Duration::ZERO;
/// One vended backing site: a fresh private temporary directory
/// holding the sqlite pool file and the large engine's root.
#[derive(Clone)]
pub(crate) struct Site {
/// The whole private directory — what teardown removes.
base: PathBuf,
/// The sqlite pool file — the kv tier's medium (the dispatch
/// oracle's kv-side counter and the durable window's rows table).
database: PathBuf,
/// The local root — the large tier's medium (the dispatch
/// oracle's file-side counter rides [`committed_file_count`]).
root: PathBuf,
}
fn fresh_site(tag: &str) -> Site {
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
static SEQ: AtomicU64 = AtomicU64::new(0);
let seq = SEQ.fetch_add(1, Ordering::Relaxed);
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0);
let base = std::env::temp_dir().join(format!(
"alkblobs-sqlite-column-{tag}-{}-{:x}-{seq}",
std::process::id(),
nanos
));
std::fs::create_dir_all(&base).expect("temp site created");
Site {
base,
database: PathBuf::new(),
root: PathBuf::new(),
}
}
impl Site {
fn with_pool(mut self) -> Site {
self.database = self.base.join("pool.db");
self.root = self.base.join("local-root");
self
}
/// The sqlite pool file path — captured before teardown so a
/// structural test can assert the removal.
pub(crate) fn database(&self) -> &Path {
&self.database
}
/// The local root path — for the file oracle's callers.
pub(crate) fn root(&self) -> &Path {
&self.root
}
fn remove(self) -> Result<(), Error> {
match std::fs::remove_dir_all(&self.base) {
Ok(()) => Ok(()),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(e) => Err(Error::Io(e.to_string())),
}
}
}
/// The dispatch-coverage factory: `kv = sqlite` + `large = local` at
/// the threshold this column declares and the test tuning of the
/// window delay (see [`TUNED_THRESHOLD`], [`WINDOW_DELAY`], and the
/// default-threshold sibling `DualTierSqliteFactory::new(
/// DEFAULT_DISPATCH_THRESHOLD)` the boundary row runs against).
///
/// **Why a fresh instance per runner (not a shared static):** teardown
/// removes the sites *this instance* vended; a shared instance's
/// teardown would race concurrently running rows' sites. Every runner
/// constructs its own and owns its lifecycle.
pub(crate) struct DualTierSqliteFactory {
/// The declared dispatch threshold — the routing boundary this
/// column's rows run at (constructor-tunable; ADR-003). Declared
/// configuration, like the local column's (the dual-tier store
/// never rejects, so there is nothing to probe).
threshold: u64,
/// The declared window delay — the durable schedule's cadence knob
/// the sweep rows run at (the test tuning: execute-on-next-sweep).
window_delay: Duration,
/// Every temp site this instance vended, for its own teardown.
sites: Mutex<Vec<Site>>,
}
impl DualTierSqliteFactory {
pub(crate) fn new(threshold: u64) -> DualTierSqliteFactory {
DualTierSqliteFactory {
threshold,
window_delay: WINDOW_DELAY,
sites: Mutex::new(Vec::new()),
}
}
/// Open + track the vended site: the shape the column's own rows
/// use (they observe the backing medium, so they need the site
/// alongside the store).
pub(crate) async fn open_tracked(&self) -> Result<(Store, Site), Error> {
let site = fresh_site("dual-tier").with_pool();
let store = Store::dual_tier_sqlite_local(
&site.database,
&site.root,
self.threshold,
self.window_delay,
)
.await?;
self.sites
.lock()
.unwrap_or_else(|e| e.into_inner())
.push(site.clone());
Ok((store, site))
}
/// The database files this instance vended, for the structural
/// tests' teardown assertions.
pub(crate) fn tracked_databases(&self) -> Vec<PathBuf> {
self.sites
.lock()
.unwrap_or_else(|e| e.into_inner())
.iter()
.map(|site| site.database.clone())
.collect()
}
}
impl StoreFactory for DualTierSqliteFactory {
fn name(&self) -> &'static str {
"dual-tier sqlite+local"
}
async fn open(&self) -> Result<Store, Error> {
self.open_tracked().await.map(|(store, _)| store)
}
async fn teardown(&self) -> Result<(), Error> {
for site in self
.sites
.lock()
.unwrap_or_else(|e| e.into_inner())
.drain(..)
{
site.remove()?;
}
Ok(())
}
}
/// The kv-only(sqlite) factory (ADR-011 §4; ADR-012 §6.2): no large
/// tier; the threshold is the put-time rejection point the kv-only
/// row discovers by probing. The durable single-node medium.
pub(crate) struct KvOnlySqliteFactory {
/// The rejection point this column's configuration declares. The
/// kv-only row discovers it behaviorally and requires it
/// materializable for its boundary legs.
pub(crate) threshold: u64,
/// The declared window delay — the durable schedule's cadence knob.
window_delay: Duration,
/// Every temp site this instance vended, for its own teardown.
sites: Mutex<Vec<Site>>,
}
impl KvOnlySqliteFactory {
pub(crate) fn new(threshold: u64) -> KvOnlySqliteFactory {
KvOnlySqliteFactory {
threshold,
window_delay: WINDOW_DELAY,
sites: Mutex::new(Vec::new()),
}
}
}
impl StoreFactory for KvOnlySqliteFactory {
fn name(&self) -> &'static str {
"kv-only(sqlite)"
}
async fn open(&self) -> Result<Store, Error> {
let site = fresh_site("kv-only").with_pool();
let store =
Store::kv_only_sqlite(&site.database, self.threshold, self.window_delay).await?;
self.sites
.lock()
.unwrap_or_else(|e| e.into_inner())
.push(site);
Ok(store)
}
async fn teardown(&self) -> Result<(), Error> {
for site in self
.sites
.lock()
.unwrap_or_else(|e| e.into_inner())
.drain(..)
{
site.remove()?;
}
Ok(())
}
}
// ------------------------------------------------------------------
// The medium oracle (the dispatch rows' instrument, adapted from the
// local column's): both tiers are on disk now, so the oracle
// distinguishes by medium — the sqlite file's pool and window tables
// vs the root's committed files.
// ------------------------------------------------------------------
/// Rows in one of the sqlite pool file's tables — the kv tier's pool
/// (`blobs`) or the durable window's staged candidates (`gc_window`),
/// counted from the test's own independent connection to the file.
fn sqlite_table_rows(database: &Path, table: &str) -> usize {
let conn = Connection::open(database).expect("the oracle connection opens");
let count: i64 = conn
.query_row(&format!("SELECT COUNT(*) FROM {table}"), [], |row| {
row.get(0)
})
.expect("the oracle query succeeds");
count.max(0) as usize
}
/// The sqlite kv tier's pool residency — exactly one row per committed
/// kv-tier entry (the CAS table's rows).
fn sqlite_pool_rows(site: &Site) -> usize {
sqlite_table_rows(site.database(), "blobs")
}
/// The durable window's staged-candidate residency — the schedule
/// observer the durable rows assert against (staged rows land here;
/// the executing sweep's take empties them).
fn sqlite_window_rows(site: &Site) -> usize {
sqlite_table_rows(site.database(), "gc_window")
}
// ------------------------------------------------------------------
// The column's own rows — the durable-schedule sweep family, the
// schedule-relative readings of the sweep-counting INV rows, and the
// local-specific forms. Every row takes this column's concrete
// factory (it observes the backing medium), is ADR-stamped per the
// convention, and traces its family.
// ------------------------------------------------------------------
/// INV-2 on the durable schedule: identical content put twice —
/// through the same put path and across the two paths — is one pool
/// entry (one row in the sqlite file), and the re-put's `Pin`
/// protects exactly as a fresh put's does. One-pool-entry is asserted
/// through durable-schedule outcomes (the INV-5 posture): the pins
/// held stage nothing; once unpinned, sweep 1 stages exactly the one
/// entry and removes nothing, and its executor sweep deletes exactly
/// that staged set — never a list comparison, and never a single-sweep
/// count (README §The schedule-relative reading for SQL-backed
/// columns).
///
/// Contract stamp: store-api.md §Invariants 2; ADR-003 (whole-value
/// put is CAS first-writer-wins); ADR-005 (a re-put refcounts the
/// existing entry under the same arbitration lock); ADR-008 §2 (the
/// staged re-arbitrated delete); ADR-012 §6.7 (the executor is the
/// next sweep — the schedule these counts read against).
pub async fn dedup_identical_content_is_one_pool_entry(factory: &DualTierSqliteFactory) {
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let content = b"deduplicated content".to_vec();
let canonical = Key::derive(&content, content.len() as u64);
let (key, first) = store
.put(Some(content.len() as u64), Cursor::new(content.as_slice()))
.await
.expect("the fresh put publishes");
let (reput, second) = store
.put(Some(content.len() as u64), Cursor::new(content.as_slice()))
.await
.expect("the same-path re-put publishes");
assert_eq!(key, canonical);
assert_eq!(reput, canonical, "one derivation, one address");
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.aborted, None);
assert_eq!(
report.candidates_staged, 0,
"one pool entry, both refcounts composing under the same lock"
);
assert_eq!(
sqlite_pool_rows(&site),
1,
"one pool entry, both refcounts — one row in the sqlite file"
);
drop(first);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
report.candidates_staged, 0,
"the re-put's pin protects exactly as a fresh put's"
);
drop(second);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 0),
"exactly one pool entry all along — staged this sweep, not executed"
);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.deleted, report.cancelled_by_arbitration),
(1, 0),
"the executing sweep deleted exactly the staged entry"
);
assert!(!store.has(&canonical.as_bytes()).await.unwrap());
assert_eq!(sqlite_pool_rows(&site), 0, "the executed delete landed");
let cross = b"deduplicated across the put paths".to_vec();
let cross_canonical = Key::derive(&cross, cross.len() as u64);
let (key, first) = store
.put(Some(cross.len() as u64), Cursor::new(cross.as_slice()))
.await
.expect("the known-length put publishes");
let (reput, second) = store
.put(None, Cursor::new(cross.as_slice()))
.await
.expect("the unknown-length re-put publishes");
assert_eq!(key, cross_canonical);
assert_eq!(reput, cross_canonical, "one pool entry across the paths");
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.candidates_staged, 0, "both refcounts compose");
drop(second);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
report.candidates_staged, 0,
"the re-put's pin protects exactly as a fresh put's (other drop order)"
);
drop(first);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 0),
"exactly one pool entry all along"
);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.deleted, 1, "executed exactly the staged set");
assert!(!store.has(&cross_canonical.as_bytes()).await.unwrap());
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
/// INV-3 on the durable schedule: stage hygiene — every put-path
/// failure leaves zero residue and every success leaves exactly one
/// committed entry, over both put paths and both injectable failure
/// modes (a mid-stream stream failure and a declared-length
/// mismatch). The kv tier's stage form is degenerate (nothing stages
/// outside a flush), so residue is the pool itself — the sqlite file's
/// rows, which the failures never touch — observed through
/// durable-schedule sweep outcomes: zero staged after every failure,
/// and a success staged exactly once, then executed exactly once.
///
/// Contract stamp: store-api.md §Invariants 3; ADR-010 §1 (the
/// staged-put contract: commit publishes, every failure path
/// discards); ADR-003 (stage-then-commit, the kv form degenerate);
/// ADR-012 §6.7 (the schedule-relative reading the success counts
/// follow).
pub async fn stage_hygiene_zero_residue_on_failure_exactly_one_entry_on_success(
factory: &DualTierSqliteFactory,
) {
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let content = patterned(200, 167);
let canonical = Key::derive(&content, content.len() as u64);
let err = store
.put(Some(content.len() as u64), Failing::new(&content, 40))
.await
.expect_err("the failed mid-stream put rejects");
assert!(
matches!(err, Error::Io(_)),
"the stream failure surfaces as Io: {err}"
);
let err = store
.put(None, Failing::new(&content, 40))
.await
.expect_err("the failed unknown-length put rejects");
assert!(
matches!(err, Error::Io(_)),
"the stream failure surfaces as Io: {err}"
);
let err = store
.put(Some(100), Cursor::new(content.as_slice()))
.await
.expect_err("the over-fed mismatch rejects");
assert_eq!(err, Error::Verification, "declared-len mismatch rejects");
let err = store
.put(Some(400), Cursor::new(content.as_slice()))
.await
.expect_err("the under-fed mismatch rejects");
assert_eq!(err, Error::Verification, "declared-len mismatch rejects");
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.aborted, None);
assert_eq!(
(
report.candidates_staged,
report.deleted,
report.cancelled_by_arbitration
),
(0, 0, 0),
"zero residue after every failure, both put paths, both failure modes"
);
assert_eq!(
sqlite_pool_rows(&site),
0,
"the pool table holds zero entries after every failure"
);
let (key, pin) = store
.put(Some(content.len() as u64), Cursor::new(content.as_slice()))
.await
.expect("the known-length put publishes");
assert_eq!(key, canonical);
drop(pin);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 0),
"exactly one committed entry staged on success"
);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
report.deleted, 1,
"the executing sweep removed exactly that one entry"
);
assert!(!store.has(&canonical.as_bytes()).await.unwrap());
let (key, pin) = store
.put(None, Cursor::new(content.as_slice()))
.await
.expect("the unknown-length put publishes");
assert_eq!(key, canonical);
drop(pin);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 0),
"exactly one committed entry staged on the other put path too"
);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.deleted, 1, "and executed exactly that staged set");
assert!(!store.has(&canonical.as_bytes()).await.unwrap());
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
/// INV-4, the durable-schedule happy shape: the full protection set
/// spanning both tiers (a source-live kv entry, a pinned large-tier
/// entry, a protect-named large-tier entry) plus one dead entry per
/// tier — sweep 1 stages exactly the two dead candidates and deletes
/// nothing (staging is not executing: the pool and the medium hold
/// everything and the window holds the staged rows); sweep 2 executes
/// exactly that staged set (`deleted + cancelled == N` against the
/// staged set), and the protected entries stay byte-identical. The
/// exact staged candidates also make this the INV-5 posture's
/// both-tiers form: list correctness (complete and well-formed across
/// both tiers' enumerations) is observable only through these
/// outcomes. The medium oracle distinguishes the tiers (the sqlite
/// file's pool rows vs the root's committed files) and watches the
/// schedule itself (the window's rows).
///
/// Contract stamp: store-api.md §Invariants 4 (exact counts with
/// correct liveness) and §Invariants 5 (list correctness through
/// sweep outcomes); ADR-005 (three liveness marks; delete windows
/// with arbitrate-at-delete-time); ADR-008 §2 (the staged
/// re-arbitrated delete; the constructor-tunable delay); ADR-012 §1
/// (sweeps are never errors — the report is the outcome record);
/// ADR-012 §6.7 (the executor is the next sweep — the schedule these
/// counts read against); ADR-007 (sqlite, the default-build kv
/// engine).
pub async fn two_sweep_exact_counts_over_the_full_protection_set(factory: &DualTierSqliteFactory) {
let threshold = factory.threshold;
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
let source = SetSource::register(&store);
let protect = Arc::new(SetProtect::default());
store.register_protect_callback(protect.clone());
let source_live = patterned((threshold - 1) as usize, 191);
let (key_live, _) = store
.put(
Some(source_live.len() as u64),
Cursor::new(source_live.as_slice()),
)
.await
.expect("the source-live entry publishes");
source.add(key_live.clone());
let pinned = patterned(2 * threshold as usize + 7, 173);
let (key_pinned, pin_pinned) = store
.put(None, Cursor::new(pinned.as_slice()))
.await
.expect("the pinned entry publishes");
let protected = patterned(2 * threshold as usize + 11, 167);
let (key_protected, _) = store
.put(
Some(protected.len() as u64),
Cursor::new(protected.as_slice()),
)
.await
.expect("the protect-named entry publishes");
protect.set_keys(vec![key_protected.clone()]);
let dead_kv = patterned((threshold - 3) as usize, 149);
let (key_dead_kv, pin) = store
.put(Some(dead_kv.len() as u64), Cursor::new(dead_kv.as_slice()))
.await
.expect("the kv-tier dead entry publishes");
drop(pin);
let dead_large = patterned(2 * threshold as usize + 13, 151);
let (key_dead_large, pin) = store
.put(None, Cursor::new(dead_large.as_slice()))
.await
.expect("the large-tier dead entry publishes");
drop(pin);
assert_eq!(
(sqlite_pool_rows(&site), committed_file_count(site.root())),
(2, 3),
"before the sweep, both tiers hold their entries exactly \
(two pool rows in the sqlite file, three committed files \
under the root)"
);
let first = store.sweep().await.expect("sweeps are never errors");
assert_eq!(first.aborted, None);
assert_eq!(
(
first.candidates_staged,
first.deleted,
first.cancelled_by_arbitration
),
(2, 0, 0),
"sweep 1 staged exactly the two dead entries and deleted \
nothing — staging is not executing"
);
assert_eq!(
sqlite_window_rows(&site),
2,
"the staged set waits in the durable window"
);
for (key, content) in [
(&key_live, &source_live),
(&key_pinned, &pinned),
(&key_protected, &protected),
] {
let (len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the protected entry is present");
assert_eq!(
blob.read_at(0, len).await.expect("the window reads"),
content.as_slice(),
"the protected entry is byte-identical after the staging sweep"
);
}
assert!(
store.has(&key_live.as_bytes()).await.unwrap()
&& store.has(&key_pinned.as_bytes()).await.unwrap()
&& store.has(&key_protected.as_bytes()).await.unwrap(),
"the staged sweep deleted nothing: every entry intact"
);
let second = store.sweep().await.expect("sweeps are never errors");
assert_eq!(second.aborted, None);
assert_eq!(
second.candidates_staged, 0,
"nothing newly dead since the staging sweep"
);
assert_eq!(
second.deleted + second.cancelled_by_arbitration,
2,
"sweep 2 executed exactly the staged set"
);
assert_eq!(
(second.deleted, second.cancelled_by_arbitration),
(2, 0),
"with correct liveness, every executed candidate deleted"
);
assert!(!store.has(&key_dead_kv.as_bytes()).await.unwrap());
assert!(!store.has(&key_dead_large.as_bytes()).await.unwrap());
assert_eq!(
(sqlite_pool_rows(&site), committed_file_count(site.root())),
(1, 2),
"the executed deletes landed on both media exactly"
);
assert_eq!(
sqlite_window_rows(&site),
0,
"the executed rows left the durable window"
);
drop(pin_pinned);
let third = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(third.candidates_staged, third.deleted),
(1, 0),
"with the pin dropped, the formerly pinned entry stages"
);
let fourth = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
fourth.deleted, 1,
"and the next sweep executes it — exactly one deletion"
);
assert!(!store.has(&key_pinned.as_bytes()).await.unwrap());
assert!(store.has(&key_live.as_bytes()).await.unwrap());
assert!(store.has(&key_protected.as_bytes()).await.unwrap());
assert_eq!(
committed_file_count(site.root()),
1,
"exactly the protect-named entry's file remains"
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
/// INV-4, the race, in its durable-schedule form: a put landing
/// *during the window* survives the executing sweep — the re-put's
/// pin is minted (pin-before-publish) between the staging sweep and
/// the executing sweep, so the execution-time re-arbitration cancels
/// the pinned candidate while the unpinned twin deletes; once the pin
/// drops, the twin re-stages and executes exactly once. Both put
/// paths race in-body over both tiers (a kv twin and a large twin).
///
/// Contract stamp: store-api.md §Invariants 4; ADR-005 (pin-before-
/// publish ordering; the delete window closes the sweep-vs-put race);
/// ADR-008 §2 (the staged re-arbitrated delete — the race holds
/// across the window delay); ADR-012 §6.7 (execution-time
/// re-arbitration is the executor sweep's posture).
pub async fn a_put_landing_during_the_window_survives_the_executing_sweep(
factory: &DualTierSqliteFactory,
) {
let threshold = factory.threshold;
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let rounds: [(String, Vec<u8>, bool, bool); 2] = [
(
"the kv twin (known-path re-put)".to_owned(),
patterned((threshold - 1) as usize, 191),
true,
true,
),
(
"the large twin (unknown-path re-put)".to_owned(),
patterned(2 * threshold as usize + 5, 173),
false,
false,
),
];
for (index, (tag, content, original_known, reput_known)) in rounds.iter().enumerate() {
let len = content.len() as u64;
let twin = Key::derive(content, len);
let witness = format!("the dead witness of round {index}").into_bytes();
let witness_key = Key::derive(&witness, witness.len() as u64);
let original = if *original_known { Some(len) } else { None };
let (_, pin) = store
.put(original, Cursor::new(content.as_slice()))
.await
.expect("the twin publishes");
drop(pin);
let (_, pin) = store
.put(None, Cursor::new(witness.as_slice()))
.await
.expect("the witness publishes");
drop(pin);
let staged = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(
staged.aborted,
staged.candidates_staged,
staged.deleted,
staged.cancelled_by_arbitration
),
(None, 2, 0, 0),
"{tag}: the staging sweep stages exactly the two dead \
twins and deletes nothing"
);
// The put lands during the window (the re-put dedups into the
// existing twin and refcounts its pin): protected across the
// delay, pin-before-publish.
let reput = if *reput_known { Some(len) } else { None };
let (_, pin) = store
.put(reput, Cursor::new(content.as_slice()))
.await
.expect("the re-put publishes");
let executed = store.sweep().await.expect("sweeps are never errors");
assert_eq!(executed.aborted, None, "{tag}");
assert_eq!(
executed.candidates_staged, 0,
"{tag}: nothing newly dead since the staging sweep"
);
assert_eq!(
executed.deleted + executed.cancelled_by_arbitration,
2,
"{tag}: the executing sweep ran exactly the staged set"
);
assert_eq!(executed.deleted, 1, "{tag}: the unpinned witness deleted");
assert_eq!(
executed.cancelled_by_arbitration, 1,
"{tag}: the pinned twin's candidate cancelled at execution time"
);
assert!(
!store.has(&witness_key.as_bytes()).await.unwrap(),
"{tag}: the unpinned twin is gone"
);
let (got_len, blob) = store
.get(&twin.as_bytes())
.await
.expect("get succeeds")
.expect("{tag}: the put landing during the window survived");
assert_eq!(got_len, len, "{tag}");
assert_eq!(
blob.read_at(0, len).await.expect("the window reads"),
content.as_slice(),
"{tag}: the surviving twin is byte-identical"
);
drop(pin);
let restaged = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(restaged.candidates_staged, restaged.deleted),
(1, 0),
"{tag}: the pin dropped — the twin re-stages"
);
let executed = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
executed.deleted, 1,
"{tag}: the re-staged candidate executes exactly once"
);
assert!(!store.has(&twin.as_bytes()).await.unwrap());
assert_eq!(
sqlite_window_rows(&site),
0,
"{tag}: the window holds nothing after the executed round"
);
}
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
/// INV-4, abort shape: the sweep is single-flight on the durable form
/// too — the in-process sweep lease (ADR-013 §2's single-node analog).
/// The contended second sweeper aborts with `SweeperLock` in a
/// completed `Ok(SweepReport)` — nothing executed, nothing staged,
/// nothing deleted (abort before staging: form-independent) — while
/// the lease holder's sweep completes by **staging only**: its staged
/// set waits in the window for the next sweep to execute (the
/// durable form's schedule-relative replacement for the reference
/// row's inline holder-completion leg).
///
/// Contract stamp: store-api.md §Invariants 4; ADR-012 §1 (abort is
/// report data, never an error); ADR-013 §2 (the named exclusive
/// sweep lease — one sweeper per pool, holdership ends at release);
/// ADR-012 §6.7 (the executor is the next sweep — the holder stages,
/// it does not execute).
pub async fn the_contended_second_sweeper_aborts_as_data_and_the_holder_stages_only(
factory: &DualTierSqliteFactory,
) {
let threshold = factory.threshold;
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let (entered_tx, entered_rx) = std::sync::mpsc::channel::<()>();
let (release_tx, release_rx) = std::sync::mpsc::channel::<()>();
store.register_protect_callback(Arc::new(LatchProtect {
entered: entered_tx,
release: parking_lot::Mutex::new(Some(release_rx)),
}));
let content = patterned((threshold - 1) as usize, 167);
let (key, pin) = store
.put(Some(content.len() as u64), Cursor::new(content.as_slice()))
.await
.expect("the dead witness publishes");
drop(pin);
// The lease holder sweeps on its own task (its protect consult
// blocks that task's thread mid-callback); this task contends and
// then releases the holder.
let store = Arc::new(store);
let holder = tokio::spawn({
let store = Arc::clone(&store);
async move { store.sweep().await }
});
while entered_rx.recv_timeout(Duration::from_millis(50)).is_err() {
tokio::task::yield_now().await;
}
let second = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
second.aborted,
Some(alkblobs::GcAbortCause::SweeperLock),
"the contended sweeper aborts as report data"
);
assert_eq!(
(
second.candidates_staged,
second.deleted,
second.cancelled_by_arbitration
),
(0, 0, 0),
"the contended sweep executes, stages, and deletes nothing"
);
assert!(
store.has(&key.as_bytes()).await.unwrap(),
"the contended sweep deleted nothing"
);
assert_eq!(
sqlite_window_rows(&site),
0,
"the aborted sweep staged nothing into the window"
);
release_tx.send(()).ok();
let report = holder
.await
.expect("the holder task joined")
.expect("sweeps are never errors");
assert_eq!(report.aborted, None, "the lease holder completes");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 0),
"the holder stages exactly the dead set — it does not execute \
(the durable form's schedule)"
);
assert_eq!(
sqlite_window_rows(&site),
1,
"the holder's staged set waits in the durable window"
);
assert!(
store.has(&key.as_bytes()).await.unwrap(),
"the holder staged, did not execute: the entry is intact"
);
let executed = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
executed.deleted, 1,
"the next sweep is the executor of the staged set"
);
assert!(!store.has(&key.as_bytes()).await.unwrap());
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
/// INV-5 on the durable schedule: `list()` correctness is observable
/// only through GC — the enumeration is complete and well-formed in
/// both directions, proven by exact durable-schedule outcomes: the
/// staging sweep stages exactly the dead set (neither more nor fewer
/// candidates), the executing sweep deletes exactly that staged set,
/// and a liveness flip re-stages exactly the newly dead entry. Never
/// a direct list comparison.
///
/// Contract stamp: store-api.md §Invariants 5; ADR-003 (`list()` is
/// complete and well-formed by contract — load-bearing for GC);
/// ADR-005 (the sweep's live-set diff rides `list()`); ADR-012 §6.7
/// (the executor is the next sweep — the schedule these counts read
/// against).
pub async fn list_correctness_is_observable_through_durable_schedule_outcomes(
factory: &DualTierSqliteFactory,
) {
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
let source = SetSource::register(&store);
let mut keys = Vec::new();
for (index, content) in [
b"kept live by the source, entry one".to_vec(),
b"kept live by the source, entry two".to_vec(),
b"dead at the first staging, entry three".to_vec(),
b"dead at the first staging, entry four".to_vec(),
b"dead at the first staging, entry five".to_vec(),
]
.into_iter()
.enumerate()
{
let declared = if index % 2 == 0 {
Some(content.len() as u64)
} else {
None
};
let (key, pin) = store
.put(declared, Cursor::new(content.as_slice()))
.await
.expect("the entry publishes");
drop(pin);
keys.push(key);
}
source.add(keys[0].clone());
source.add(keys[1].clone());
let first = store.sweep().await.expect("sweeps are never errors");
assert_eq!(first.aborted, None);
assert_eq!(
(first.candidates_staged, first.deleted),
(3, 0),
"the enumeration staged exactly the three dead entries — \
complete and well-formed in both directions"
);
for key in &keys {
assert!(
store.has(&key.as_bytes()).await.unwrap(),
"staging deleted nothing: every enumerated entry is intact"
);
}
assert_eq!(
sqlite_window_rows(&site),
3,
"the staged schedule holds the three candidates"
);
let second = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(second.candidates_staged, second.deleted),
(0, 3),
"the executing sweep removed exactly the staged set"
);
assert!(store.has(&keys[0].as_bytes()).await.unwrap());
assert!(store.has(&keys[1].as_bytes()).await.unwrap());
for key in &keys[2..] {
assert!(!store.has(&key.as_bytes()).await.unwrap());
}
source.remove(&keys[1]);
let third = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(third.candidates_staged, third.deleted),
(1, 0),
"the newly dead entry is staged exactly"
);
let fourth = store.sweep().await.expect("sweeps are never errors");
assert_eq!(fourth.deleted, 1, "and executed exactly by the next sweep");
assert!(!store.has(&keys[1].as_bytes()).await.unwrap());
assert!(store.has(&keys[0].as_bytes()).await.unwrap());
source.remove(&keys[0]);
let fifth = store.sweep().await.expect("sweeps are never errors");
assert_eq!(fifth.candidates_staged, 1, "the last entry stages exactly");
let sixth = store.sweep().await.expect("sweeps are never errors");
assert_eq!(sixth.deleted, 1, "and executes exactly");
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
/// Dispatch row: **routing is a pure function of length** — at, below,
/// and over the declared threshold, the same content lands on exactly
/// the same tier through both put paths (same placement every time;
/// nothing moves, nothing duplicates), identical content through both
/// paths is one pool entry, and every read is byte-identical from
/// wherever that tier holds it.
///
/// Tier placement is observed through the backing medium (the module
/// doc's oracle, adapted): kv entries hold a row in the sqlite file
/// and none under the root; large entries hold a committed file under
/// the root and no pool row — the facade cannot and must not expose
/// tier residency (it is engine-blind).
///
/// Contract stamp: store-api.md §Invariants 7 (facade-contract row);
/// ADR-003 §Dispatch policy (routing is a pure function of length;
/// no migration; CAS first-writer-wins makes re-puts one entry);
/// ADR-005 (re-put refcounts); ADR-007 (sqlite, the default-build
/// kv engine); ADR-012 §6.3 (the dual-tier dispatch-coverage shape);
/// ADR-012 §6.7 (the schedule-relative cleanup the dedup legs read
/// against).
pub async fn routing_is_a_pure_function_of_length_across_put_paths_and_re_puts(
factory: &DualTierSqliteFactory,
) {
let threshold = factory.threshold;
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
for content in [
patterned((threshold - 1) as usize, 191),
patterned(threshold as usize, 173),
patterned((threshold + 1) as usize, 167),
patterned(4 * threshold as usize + 9, 151),
] {
let len = content.len() as u64;
let canonical = Key::derive(&content, len);
let expected_rows = if len > threshold { 0 } else { 1 };
let expected_files = if len > threshold { 1 } else { 0 };
for (path_tag, declared) in [("the known path", Some(len)), ("the unknown path", None)] {
let (key, pin) = store
.put(declared, Cursor::new(content.as_slice()))
.await
.expect("put publishes");
assert_eq!(
key, canonical,
"the canonical derivation addresses the put on {path_tag}"
);
assert_eq!(
sqlite_pool_rows(&site),
expected_rows,
"length {len} on {path_tag}: the placement is exactly the \
routing function's answer and never moves or duplicates \
(the sqlite medium holds {expected_rows} kv rows)"
);
assert_eq!(
committed_file_count(site.root()),
expected_files,
"length {len} on {path_tag}: the large-tier medium holds \
{expected_files} committed files"
);
assert_eq!(
staging_file_count(site.root()),
0,
"a published put leaves no stage file on {path_tag}"
);
let (got_len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the entry is present");
assert_eq!(
got_len, len,
"the read serves the entry from its placed tier"
);
assert_eq!(
blob.read_at(0, len).await.expect("the whole window reads"),
content,
"the entry is byte-identical from its placed tier across paths"
);
drop(pin);
}
let staged = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
staged.candidates_staged, 1,
"identical content through both put paths is one pool entry"
);
let executed = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
executed.deleted, 1,
"the executing sweep removed exactly the one entry (durable \
schedule: staged this sweep, executed by the next)"
);
assert_eq!(
(sqlite_pool_rows(&site), committed_file_count(site.root())),
(0, 0),
"both media are back to zero"
);
}
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
/// Dispatch row: **threshold boundary lengths route deterministically**
/// — at/below/above the factory's declared threshold, on both put
/// paths, the placement is the routing function's answer every time
/// (the medium oracle distinguishes the sqlite file's rows from the
/// root's committed files); and the default-threshold boundary
/// re-routes with the tuning (the constructor-tuned threshold
/// deterministically places the default boundary's length on the tier
/// its own threshold names). Run against two factories by the runner
/// — the column's tuned threshold and the shipped default — the same
/// row shape at two declared thresholds being the tunable re-route
/// demonstration. The durable cleanup: the staged sweep stages exactly
/// the six entries' dead set and the next sweep executes it.
///
/// Contract stamp: store-api.md §Invariants 7 (facade-contract row);
/// ADR-003 §Dispatch policy (default 128 KiB at-or-below routes kv;
/// constructor-tunable without API change); ADR-007 (sqlite, the
/// default-build kv engine); ADR-012 §6.3 (the dual-tier
/// dispatch-coverage shape); ADR-012 §6.7 (schedule-relative cleanup).
pub async fn threshold_boundary_lengths_route_deterministically(factory: &DualTierSqliteFactory) {
let threshold = factory.threshold;
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let boundary = [
(threshold - 1, 191u32, false),
(threshold, 173, false),
(threshold, 167, false),
(threshold + 1, 151, true),
(threshold + 1, 139, true),
];
let mut expected_rows = 0u64;
let mut expected_files = 0u64;
for (len, modulus, lands_large) in boundary {
let content = patterned(len as usize, modulus);
for declared in [Some(content.len() as u64), None] {
let (key, pin) = store
.put(declared, Cursor::new(content.as_slice()))
.await
.expect("put publishes");
assert_eq!(
key,
Key::derive(&content, len),
"the canonical derivation addresses the put"
);
assert_eq!(
sqlite_pool_rows(&site) as u64,
expected_rows + if lands_large { 0 } else { 1 },
"boundary length {len}: at/below the threshold lands kv \
(one row in the sqlite file), over it lands large (a \
committed file instead), both put paths"
);
assert_eq!(
committed_file_count(site.root()) as u64,
expected_files + if lands_large { 1 } else { 0 },
"boundary length {len}: the large-tier medium matches the \
routing answer"
);
drop(pin);
}
if lands_large {
expected_files += 1;
} else {
expected_rows += 1;
}
}
// The default boundary re-routes with the constructor's tuning:
// the shipped default's length belongs to the tier this
// configuration's own threshold puts it on.
let at_default = patterned(DEFAULT_DISPATCH_THRESHOLD as usize, 199);
let default_lands_large = DEFAULT_DISPATCH_THRESHOLD > threshold;
let (key, pin) = store
.put(
Some(DEFAULT_DISPATCH_THRESHOLD),
Cursor::new(at_default.as_slice()),
)
.await
.expect("the default-boundary put publishes");
assert_eq!(
key,
Key::derive(&at_default, DEFAULT_DISPATCH_THRESHOLD),
"the canonical derivation addresses the put"
);
assert_eq!(
sqlite_pool_rows(&site) as u64,
expected_rows + if default_lands_large { 0 } else { 1 },
"the default boundary's length routes to the tier this \
configuration's tuning names (the sqlite medium's answer)"
);
assert_eq!(
committed_file_count(site.root()) as u64,
expected_files + if default_lands_large { 1 } else { 0 },
"the default boundary's length routes to the tier this \
configuration's tuning names (the large medium's answer)"
);
drop(pin);
let staged = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
staged.candidates_staged, 6,
"each leg's content was exactly one pool entry"
);
let executed = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
executed.deleted, 6,
"the executing sweep removed every entry, tier notwithstanding"
);
assert_eq!(
(sqlite_pool_rows(&site), committed_file_count(site.root())),
(0, 0),
"both media are back to zero"
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
/// Dispatch row: **a kv-tier miss falls through to the large tier on
/// every key-addressed op** — content the routing function placed on
/// the large tier (one committed file under the root; the sqlite
/// medium holds no pool row — the kv tier misses) serves `get`,
/// `stat`, `has`, and `read_range` whole, exact, and digest-correct;
/// the mirror-position leg proves the kv tier is the *first* consult
/// (sub-threshold content, one sqlite row and no committed file,
/// reads still served); and both-tier misses resolve per the error
/// model's per-op shapes (reached here by the durable schedule's
/// staged-then-executed deletion of the subject entry).
///
/// Contract stamp: store-api.md §Read path (fall-through consult
/// order); ADR-012 §6.1 (every key-addressed op consults kv first,
/// then large; the general rule); ADR-012 §6.5 ruling 5 (both-tier
/// miss shapes: `None` on get/stat, `Err(Missing)` on read_range);
/// ADR-006 (the slice digest); ADR-007 (sqlite, the default-build
/// kv engine); ADR-012 §6.3 (the dispatch-coverage shape).
pub async fn kv_tier_misses_fall_through_to_the_large_tier_per_op(factory: &DualTierSqliteFactory) {
let threshold = factory.threshold;
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
// Over-threshold content — the kv tier misses, the large tier
// serves every op. Both put paths hold the shape.
for (content, declared) in [
(
patterned(3 * threshold as usize + 41, 181),
Some(3 * threshold + 41),
),
(patterned(3 * threshold as usize + 43, 197), None),
] {
let len = content.len() as u64;
let (key, pin) = store
.put(declared, Cursor::new(content.as_slice()))
.await
.expect("put publishes");
assert_eq!(
(sqlite_pool_rows(&site), committed_file_count(site.root())),
(0, 1),
"the content lives on exactly the large tier — the kv tier \
misses"
);
let (got_len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the large tier served the kv miss");
assert_eq!(got_len, len);
assert_eq!(
blob.read_at(0, len).await.expect("the whole window reads"),
content,
"the fall-through read is byte-identical"
);
assert_eq!(
store.stat(&key.as_bytes()).await.expect("stat succeeds"),
Some(alkblobs::EntryMeta {
len,
algorithm: key.algorithm(),
}),
"stat falls through and carries the length plus algorithm"
);
assert!(
store.has(&key.as_bytes()).await.unwrap(),
"has falls through"
);
let mid = len / 2;
let (slice, digest) = store
.read_range(&key.as_bytes(), mid, 17)
.await
.expect("read_range falls through");
assert_eq!(
slice,
content[(mid as usize)..(mid as usize + 17)],
"the range slice is exact"
);
assert_eq!(
digest,
slice_digest(&slice),
"the slice digest is SHA-256 over exactly the returned bytes"
);
// Sweep the entry away (the pin dropped): the miss shapes now
// resolve per op — the large tier misses too. The durable
// schedule: staged this sweep, executed by the next.
drop(pin);
let staged = store.sweep().await.expect("sweeps are never errors");
assert_eq!((staged.candidates_staged, staged.deleted), (1, 0));
let executed = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
executed.deleted, 1,
"exactly the one entry died across the two sweeps"
);
assert!(
store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.is_none(),
"a both-tier miss on get is Ok(None)"
);
assert_eq!(
store.stat(&key.as_bytes()).await.expect("stat succeeds"),
None,
"a both-tier miss on stat is Ok(None)"
);
assert!(
!store.has(&key.as_bytes()).await.unwrap(),
"a both-tier miss on has is false"
);
assert_eq!(
store
.read_range(&key.as_bytes(), 0, 4)
.await
.expect_err("the both-tier miss errs"),
Error::Missing,
"a both-tier miss on read_range is Err(Missing)"
);
}
// The mirror-position leg: sub-threshold content — the kv tier is
// the first consult and serves before the large tier is reached
// (one row in the sqlite file; no committed file ever lands).
let small = patterned((threshold - 1) as usize, 149);
let (key, pin) = store
.put(Some(small.len() as u64), Cursor::new(small.as_slice()))
.await
.expect("the sub-threshold put publishes");
assert_eq!(
(sqlite_pool_rows(&site), committed_file_count(site.root())),
(1, 0),
"the kv tier holds the sub-threshold entry — the large tier was \
never consulted on the write, never reached on the read"
);
let (len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the kv tier served");
assert_eq!(len, small.len() as u64);
assert_eq!(
blob.read_at(0, len).await.expect("the whole window reads"),
small
);
drop(pin);
// Both-tier miss shapes for a key that never existed at all, per
// op, over the fresh both-tier store.
let absent = b"never put here".to_vec();
let absent = Key::derive(&absent, absent.len() as u64);
assert!(
store
.get(&absent.as_bytes())
.await
.expect("get succeeds")
.is_none(),
"never-put: get is Ok(None)"
);
assert_eq!(
store.stat(&absent.as_bytes()).await.expect("stat succeeds"),
None,
"never-put: stat is Ok(None)"
);
assert!(
!store.has(&absent.as_bytes()).await.unwrap(),
"never-put: has is false"
);
assert_eq!(
store
.read_range(&absent.as_bytes(), 0, 4)
.await
.expect_err("never-put read_range errs"),
Error::Missing,
"never-put: read_range is Err(Missing)"
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
/// Virgin-store row: **reads are no-ops on a fresh file** — an empty
/// `list`, absent reads per op (`None` on get/stat, `false` on has,
/// `Err(Missing)` on read_range), and nothing on the fresh medium
/// itself (zero pool rows, zero window rows, zero committed files).
/// The sqlite engine's no-tables-yet read tolerance (every read
/// against a genuinely tableless database file is a no-op, never a
/// "table does not exist" error) is instrumented engine-side — a
/// store constructor always ensures the schema — so the facade's
/// fresh-file form of the tolerance is this row's assertions.
///
/// Contract stamp: store-api.md §Error model (virgin-store semantics:
/// reads on a fresh store see absent/empty, never errors); ADR-012
/// §6.5 ruling 5 (the per-op miss shapes); ADR-007 (the sqlite
/// engine — the read tolerance's engine-level posture and the
/// schema-creation timing design point).
pub async fn virgin_store_reads_are_no_ops_on_a_fresh_file(factory: &DualTierSqliteFactory) {
let (store, site) = factory
.open_tracked()
.await
.expect("open vends a fresh, isolated store");
assert_eq!(
store.mode(),
StoreMode::DualTier,
"the column's factory is the dispatch-coverage shape"
);
let absent = b"nothing was ever put".to_vec();
let absent = Key::derive(&absent, absent.len() as u64);
assert_eq!(
store.list().await.expect("list succeeds"),
Vec::<Key>::new(),
"the virgin pool lists empty"
);
assert!(
store
.get(&absent.as_bytes())
.await
.expect("get succeeds")
.is_none(),
"absent get is Ok(None)"
);
assert_eq!(
store.stat(&absent.as_bytes()).await.expect("stat succeeds"),
None,
"absent stat is Ok(None)"
);
assert!(
!store.has(&absent.as_bytes()).await.unwrap(),
"absent has is false"
);
assert_eq!(
store
.read_range(&absent.as_bytes(), 0, 4)
.await
.expect_err("absent read_range errs"),
Error::Missing,
"absent read_range is Err(Missing)"
);
assert_eq!(
(
sqlite_pool_rows(&site),
sqlite_window_rows(&site),
committed_file_count(site.root())
),
(0, 0, 0),
"the fresh medium holds nothing (pool, durable window, and \
committed tree all empty)"
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
// ------------------------------------------------------------------
// The runners — the column's tests: the form-independent reference
// rows mirrored verbatim against the dual-tier factory (INV-1, INV-6,
// and the two no-op abort shapes), the durable-schedule rows above,
// the kv-only rejection row against the kv-only factory (unchanged —
// threshold-agnostic by discovery), and the factory contract's
// structural shapes.
// ------------------------------------------------------------------
#[tokio::test]
async fn sqlite_inv1_round_trip_puts_and_gets_are_byte_identical() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
rows::round_trip_puts_and_gets_are_byte_identical(&factory).await;
}
#[tokio::test]
async fn sqlite_inv2_dedup_identical_content_is_one_pool_entry() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
dedup_identical_content_is_one_pool_entry(&factory).await;
}
#[tokio::test]
async fn sqlite_inv3_stage_hygiene_zero_residue_one_entry_on_success() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
stage_hygiene_zero_residue_on_failure_exactly_one_entry_on_success(&factory).await;
}
#[tokio::test]
async fn sqlite_inv4_two_sweep_exact_counts_over_the_full_protection_set() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
two_sweep_exact_counts_over_the_full_protection_set(&factory).await;
}
#[tokio::test]
async fn sqlite_inv4_a_put_landing_during_the_window_survives_the_executing_sweep() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
a_put_landing_during_the_window_survives_the_executing_sweep(&factory).await;
}
#[tokio::test]
async fn sqlite_inv4_sweep_without_liveness_sources_aborts_and_deletes_nothing() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
rows::sweep_without_liveness_sources_aborts_and_deletes_nothing(&factory).await;
}
#[tokio::test]
async fn sqlite_inv4_sweep_with_a_failed_protect_callback_aborts_and_deletes_nothing() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
rows::sweep_with_a_failed_protect_callback_aborts_and_deletes_nothing(&factory).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn sqlite_inv4_the_contended_second_sweeper_aborts_as_data_and_the_holder_stages_only() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
the_contended_second_sweeper_aborts_as_data_and_the_holder_stages_only(&factory).await;
}
#[tokio::test]
async fn sqlite_inv5_list_correctness_through_durable_schedule_outcomes() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
list_correctness_is_observable_through_durable_schedule_outcomes(&factory).await;
}
#[tokio::test]
async fn sqlite_inv6_stat_reports_len_and_algorithm_without_fetching_content() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
rows::stat_reports_len_and_algorithm_without_fetching_content(&factory).await;
}
#[tokio::test]
async fn sqlite_virgin_store_reads_are_no_ops_on_a_fresh_file() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
virgin_store_reads_are_no_ops_on_a_fresh_file(&factory).await;
}
#[tokio::test]
async fn sqlite_kv_only_mode_rejects_over_threshold_puts_at_put_time() {
let factory = KvOnlySqliteFactory::new(KV_ONLY_THRESHOLD);
rows::kv_only_mode_rejects_over_threshold_puts_at_put_time(&factory).await;
}
#[tokio::test]
async fn dispatch_routing_is_a_pure_function_of_length_across_put_paths_and_re_puts() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
routing_is_a_pure_function_of_length_across_put_paths_and_re_puts(&factory).await;
}
#[tokio::test]
async fn dispatch_threshold_boundary_lengths_route_deterministically() {
let tuned = DualTierSqliteFactory::new(TUNED_THRESHOLD);
threshold_boundary_lengths_route_deterministically(&tuned).await;
let default = DualTierSqliteFactory::new(DEFAULT_DISPATCH_THRESHOLD);
threshold_boundary_lengths_route_deterministically(&default).await;
}
#[tokio::test]
async fn dispatch_kv_tier_misses_fall_through_to_the_large_tier_per_op() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
kv_tier_misses_fall_through_to_the_large_tier_per_op(&factory).await;
}
// ------------------------------------------------------------------
// The factory contract's structural shapes (the mem and local
// columns' pattern, carried to the SQL-backed medium-backed factory):
// fresh isolated opens (fresh site per open, nothing shared) and
// idempotent teardown safe against a panicking row. Not conformance
// rows — no backlog entry — the factory contract's own wiring-level
// assertions.
// ------------------------------------------------------------------
/// Every `open()` vends a fresh, isolated store: no shared state
/// between islands, observable on the facade *and* on the fresh media
/// (each open's sqlite file and root are private and start empty).
#[tokio::test]
async fn factory_open_vends_fresh_isolated_sqlite_stores() {
let factory = DualTierSqliteFactory::new(TUNED_THRESHOLD);
let (a, site_a) = factory.open_tracked().await.expect("open vends a store");
let (b, site_b) = factory.open_tracked().await.expect("open vends another");
assert_ne!(
site_a.database(),
site_b.database(),
"two opens never share a sqlite file"
);
assert_ne!(
site_a.root(),
site_b.root(),
"two opens never share a local root"
);
let content_a = patterned(2 * TUNED_THRESHOLD as usize + 5, 167);
let content_b = patterned(TUNED_THRESHOLD as usize - 5, 191);
let (key_a, _) = a
.put(
Some(content_a.len() as u64),
Cursor::new(content_a.as_slice()),
)
.await
.expect("island a's put publishes");
let (key_b, _) = b
.put(None, Cursor::new(content_b.as_slice()))
.await
.expect("island b's put publishes");
assert!(a.has(&key_a.as_bytes()).await.unwrap());
assert!(
!a.has(&key_b.as_bytes()).await.unwrap(),
"island a sees nothing of island b"
);
assert!(b.has(&key_b.as_bytes()).await.unwrap());
assert!(
!b.has(&key_a.as_bytes()).await.unwrap(),
"island b sees nothing of island a"
);
assert_eq!(
(
sqlite_pool_rows(&site_a),
committed_file_count(site_a.root())
),
(0, 1),
"island a's media hold exactly its own entry (a's content routes large)"
);
assert_eq!(
(
sqlite_pool_rows(&site_b),
committed_file_count(site_b.root())
),
(1, 0),
"island b's media hold exactly its own entry (b's content routes kv)"
);
let (c, site_c) = factory.open_tracked().await.expect("a third vends fresh");
assert_eq!(
(
sqlite_pool_rows(&site_c),
committed_file_count(site_c.root())
),
(0, 0),
"a third open's media are virgin"
);
assert!(
!c.has(&key_a.as_bytes()).await.unwrap(),
"a third open shares nothing with the first"
);
assert!(
!c.has(&key_b.as_bytes()).await.unwrap(),
"a third open shares nothing with the second"
);
factory
.teardown()
.await
.expect("teardown removes the sites");
factory.teardown().await.expect("teardown repeats cleanly");
}
/// A failing assertion panics the row before teardown runs — and
/// teardown must make sense over the abandoned instance anyway: it is
/// idempotent against the panicked row's path, the vended files are
/// really gone, and the next open vends a fresh store on a fresh
/// (empty) medium (README §The factory contract).
#[tokio::test]
async fn factory_teardown_is_safe_against_a_panicking_row() {
let content = patterned(TUNED_THRESHOLD as usize - 7, 173);
let abandoned = Key::derive(&content, content.len() as u64);
let factory = Arc::new(DualTierSqliteFactory::new(TUNED_THRESHOLD));
let task = {
let factory = Arc::clone(&factory);
tokio::spawn(async move {
let (store, _) = factory.open_tracked().await.expect("open vends the store");
let (_, pin) = store
.put(Some(content.len() as u64), Cursor::new(content.as_slice()))
.await
.expect("the put publishes");
drop(pin);
panic!("a failing assertion panics the row (the factory contract's early exit)");
})
};
assert!(
task.await.is_err(),
"the row's panic surfaced as its failure"
);
let databases = factory.tracked_databases();
assert!(!databases.is_empty(), "the panicked row vended a site");
factory
.teardown()
.await
.expect("teardown makes sense over the abandoned instance");
factory.teardown().await.expect("teardown is idempotent");
for database in databases {
assert!(
!database.exists(),
"teardown removed the panicked row's sqlite file: {database:?}"
);
}
let (store, site) = factory
.open_tracked()
.await
.expect("the next open still vends a store");
assert!(
!store.has(&abandoned.as_bytes()).await.unwrap(),
"no residue from the panicked row — isolation is factory-owned"
);
assert_eq!(
(sqlite_pool_rows(&site), committed_file_count(site.root())),
(0, 0),
"and its media carry nothing of the abandoned run"
);
factory
.teardown()
.await
.expect("teardown removes the last site");
}