Files
alkblobs/tests/conformance/factory.rs
T
glm-5.3-flash 532adfa707 feat(store): the Store facade — constructor modes, size-threshold dispatch, the factory binding
The wave-2 facade skeleton and routing (tasks/store-construction.md):
the public surface consumers program against, with the ops methods
still to land against it in store-read-paths/gc-protocol/store-put-paths.

- src/store.rs — the public `Store` type (engine-blind, ADR-007/008/
  010) over crate-internal tier enums (`KvEngine`{mem}, `LargeEngine`{
  local}): the engine-representation design point decided as concrete
  + enum dispatch, generic rejected (pub(crate) engines, no dyn);
  the three constructor modes as named constructors — `mem_only`,
  `kv_only_mem`, `dual_tier_mem_local` (the ADR-012 §6.3
  dispatch-coverage shape) — with `StoreMode` introspection; the
  write-side routing seam (`tier_for`), the read-side fall-through
  order (`kv()` then `large()`, ADR-012 §6.1), and the `GcHome`
  GC-state field; the ADR-012 §3 fleet declaration ruled deferred to
  the engine waves (nothing fleet-valid is constructible yet)
- src/dispatch.rs — the pure routing function (`route`, at-or-below
  → kv), `DEFAULT_DISPATCH_THRESHOLD` (128 KiB) exported at the
  crate root, boundary-value unit tests (exactly-at-threshold,
  degenerate tunings, purity)
- src/gc.rs — `GcHome`: the store-instance GC-state home the
  gc-protocol task fills (in-process; fleet state stays on the
  engine-state seam per ADR-010 §2/ADR-012 §4)
- tests/conformance — the wave-2 binding made as anticipated: the
  factory's `Store` associated type collapsed into the concrete
  `alkblobs::Store` (`open` vends it directly), recorded in
  factory.rs + README; the wave-1 mock probe retired, replaced by
  mem-gated binding demo factories (binding.rs) over both
  constructible shapes

Verification: `cargo test` (default), `cargo test --features mem`,
`cargo test --all-features` green (41/53/53 unit + conformance
targets green in all three shapes); `cargo clippy --all-targets
-- -D warnings` green in all three feature shapes; `cargo fmt
--check` green; `cargo doc --no-deps` adds no warnings beyond the
pre-existing private-intra-doc-links class.
2026-10-11 22:18:32 +00:00

70 lines
3.5 KiB
Rust

//! The suite's factory contract (the alkstore `StoreFactory` pattern
//! adapted — docs/plans/implementation.md, decided point "Contract-
//! suite home").
//!
//! One shape, deliberately minimal: open a **fresh, isolated** store
//! instance per call (no state shared between rows or between
//! columns), with **idempotent teardown** — the full contract text is
//! the suite README §The factory contract. Engines implement this in
//! wave 2+'s column wiring; rows take factories, never stores.
//!
//! **The wave-2 binding — made, recorded.** The `Store` facade type
//! landed with wave 2's store-construction task as a concrete type
//! (`alkblobs::Store`) whose engine representation is crate-internal
//! enum dispatch over the closed five-engine set — the collapse this
//! skeleton's note anticipated ("most plausibly the associated type
//! collapsing to the concrete facade type across all factories"). The
//! binding made that correction: there **is no `Store` associated
//! type** — [`StoreFactory::open`] vends the concrete facade type
//! directly, so every impl binds by construction and no factory can
//! vend anything else. The original associated-type shape was
//! plausible when the facade was unwritten and possibly generic; with
//! the concrete engine-blind type, a second vendible type would be the
//! surprise, so the placeholder collapsed into the contract.
//!
//! The SKIP posture is a factory-owner responsibility (README §SKIP
//! posture): SQL-attached factories probe their server before rows
//! run; an unreachable server skips the column cleanly, while the
//! engine wave's acceptance requires green against the server.
#![allow(dead_code)]
use std::future::Future;
use alkblobs::{Error, Store};
/// Vends fresh, isolated store instances to the suite's rows.
///
/// Implementers — the engine columns' wiring — yield an instance of
/// the concrete `Store` facade over an isolated backing store (fresh
/// temp directory, pool, file, or schema per call, so a property's
/// rows never outlive their run into another's) plus a teardown
/// disposing of the backing store. Implementations must be `Send +
/// Sync` so one factory instance can be shared across row runs.
///
/// Rows call [`StoreFactory::open`], drive their assertions, and call
/// [`StoreFactory::teardown`] before returning; a failing assertion
/// panics the row (no teardown on that path), which is why teardown is
/// required to be idempotent and safe against an abandoned instance.
pub trait StoreFactory: Send + Sync {
/// The column's identity for reporting — which configuration rows
/// ran against (the constructor-mode vocabulary of ADR-011 §4).
/// Rows never branch on it; the suite's reporting and the SKIP
/// posture's per-column bookkeeping do.
fn name(&self) -> &'static str;
/// Vend a fresh, isolated store instance — the concrete `alkblobs::Store`
/// facade (the wave-2 binding, made and recorded above). A failure
/// here is an environment failure (e.g. the SKIP posture's
/// unreachable server), not a row failure.
fn open(&self) -> impl Future<Output = Result<Store, Error>> + Send;
/// Tear down the backing store behind this factory instance.
///
/// Idempotent per instance. The factory owns what teardown means —
/// deleting the temp directory, dropping the schema, closing the
/// pool — and owns the isolated-ness guarantee: no two `open`
/// calls ever share state.
fn teardown(&self) -> impl Future<Output = Result<(), Error>> + Send;
}