Files
alkstore/alkstore-sqlite/src/opts.rs
T
glm-5.3-flash 7d400906f5 SQLite engine open: SqliteOpts, connection architecture, spawn_blocking seam posture (task sqlite-engine-open-opts)
- 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
2026-10-08 11:25:16 +00:00

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),
}
}
}