alkblobs 0.2.2

Content-addressed blob storage: multi-hash put/get/verify store with pluggable backends, transport- and protocol-agnostic
Documentation
//! 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;
}