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.
70 lines
3.5 KiB
Rust
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;
|
|
}
|