//! 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> + 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> + Send; }