- SqliteOpts (poll_interval: Option<Duration>, None = 1 ms shipping default ADR-023 §4; max_readers, DEFAULT_MAX_READERS = 8; opts exemption from non_exhaustive per ADR-017 §3) - open(path, opts) -> Box<dyn Store>: writer slot, reader pool, SharedUpdateWatcher with fallible spawn mapped W-2-style into Error::Database; plain-path posture (ADR-023 §3) pinned by test - Substrate delta D-30: open_conn_bootstrapped — every connection (writer and pooled readers) carries the full bootstrap surface (pragmas, notify, alkstore functions, schema) per engine-sqlite.md; lineage opened readers pragmas-only. Registered in PROVENANCE.md - spawn_blocking seam helper + error mappings (string/rusqlite -> Database, source chains preserved); helper cfg(test)-gated until sqlite-engine-seam-tx wires the trait impls - Store trait stubbed with Database errors (no panics); close()/Drop join the watcher, clear subscribers (death-guard), close pool+writer - 15 new tests (open boot, watcher fanout/death-close, cadence accounting, plain-path literal filename, :memory:, pool bounding, drop teardown, seam smoke incl. panic mapping); gates green
69 lines
2.7 KiB
Rust
69 lines
2.7 KiB
Rust
//! The SQLite engine's option struct and the watcher-config plumbing
|
|
//! (ADR-008 §6 — constructors and their option structs live in the
|
|
//! engine crates; engine-configuration concerns never touch the
|
|
//! contract surface).
|
|
//!
|
|
//! `#[non_exhaustive]` deliberately does not apply (ADR-017 §3): opts
|
|
//! structs are consumer-*constructed*, and the attribute on them would
|
|
//! push every construction through a builder. New fields may be added
|
|
//! with `Default` fallbacks, per the core opts modules' posture.
|
|
|
|
use std::time::Duration;
|
|
|
|
use crate::substrate::WatcherConfig;
|
|
|
|
/// The default reader-pool size (the shared watcher's poll cadence
|
|
/// rides [`SqliteOpts::poll_interval`]; this is the pool's own knob).
|
|
pub const DEFAULT_MAX_READERS: usize = 8;
|
|
|
|
/// Construction options for the SQLite engine's
|
|
/// [`open`](crate::open) constructor.
|
|
///
|
|
/// Durability knobs, pool sizing, and the watcher cadence are
|
|
/// engine-configuration concerns — they never appear on the contract
|
|
/// surface (ADR-008 §6); deployment.md carries the documented tuning
|
|
/// facts.
|
|
#[derive(Debug, Clone)]
|
|
pub struct SqliteOpts {
|
|
/// The watcher's `PRAGMA data_version` poll cadence. `None` = the
|
|
/// substrate's 1 ms shipping default (ADR-023 §4 — the default the
|
|
/// published wake-latency numbers were measured at); `Some(d)` sets
|
|
/// an explicit cadence (raise it for latency-tolerant deployments —
|
|
/// the documented idle cost at 1 ms is ~1000 poll reads/sec per
|
|
/// instance). Zero is rejected at `open` with
|
|
/// [`Error::Database`](alkstore::Error::Database) (the substrate's
|
|
/// `WatcherConfig::with_poll_interval` rejects zero; the mapping is
|
|
/// engine-layer work per ADR-012 §4's W-2 posture).
|
|
pub poll_interval: Option<Duration>,
|
|
/// Upper bound on pooled reader connections (claims/lookups ride
|
|
/// these). Fresh readers open on demand up to the bound; `0` clamps
|
|
/// to 1.
|
|
pub max_readers: usize,
|
|
}
|
|
|
|
impl Default for SqliteOpts {
|
|
fn default() -> Self {
|
|
Self {
|
|
poll_interval: None,
|
|
max_readers: DEFAULT_MAX_READERS,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SqliteOpts {
|
|
/// Resolve this opts into the substrate's
|
|
/// [`WatcherConfig`](crate::substrate::WatcherConfig), mapping the
|
|
/// substrate's string error into the contract taxonomy's
|
|
/// [`Error::Database`](alkstore::Error) arm (the W-2 posture —
|
|
/// engine-layer mapping, ADR-012 §4).
|
|
pub(crate) fn watcher_config(&self) -> Result<WatcherConfig, alkstore::Error> {
|
|
let config = WatcherConfig::default();
|
|
match self.poll_interval {
|
|
None => Ok(config),
|
|
Some(d) => config
|
|
.with_poll_interval(d)
|
|
.map_err(alkstore::Error::database),
|
|
}
|
|
}
|
|
}
|