Skip to main content

codlet_sqlx/
lib.rs

1//! SQLite storage adapters for codlet (RFC-011).
2//!
3//! Each adapter is a thin wrapper around a [`sqlx::SqlitePool`] that
4//! implements the corresponding `codlet-core` store trait using SQLite's
5//! conditional `UPDATE` semantics for atomic single-winner operations
6//! (RFC-022).
7//!
8//! ## Usage
9//!
10//! ```rust,ignore
11//! use codlet_sqlx::{SqliteStore, run_migrations};
12//!
13//! let pool = sqlx::SqlitePool::connect("sqlite::memory:").await?;
14//! run_migrations(&pool).await?;
15//! let store = SqliteStore::new(pool);
16//! // store implements CodeStore + SessionStore + FormTokenStore
17//! ```
18//!
19//! ## Atomicity guarantee
20//!
21//! Every one-time transition (code claim, form-token consume) uses a single
22//! `UPDATE … WHERE … AND <guard condition>` followed by an affected-row count
23//! check. SQLite's serialised write mode ensures these are atomic under
24//! concurrent access from multiple threads within the same process. For
25//! multi-process deployments (rare for codlet's target use case), WAL mode
26//! and appropriate busy-timeout settings are recommended.
27//!
28//! ## Conformance
29//!
30//! All three stores pass the full `codlet-conformance` suite, including the
31//! concurrent-claim race test (RFC-022, RFC-023).
32
33#![forbid(unsafe_code)]
34
35pub mod code;
36pub mod migration;
37pub mod session;
38pub mod token;
39
40pub use migration::run_migrations;
41
42/// A handle wrapping a [`sqlx::SqlitePool`] that implements all three
43/// codlet store traits.
44///
45/// Clone is cheap (the pool is reference-counted internally).
46#[derive(Debug, Clone)]
47pub struct SqliteStore {
48    pool: sqlx::SqlitePool,
49}
50
51impl SqliteStore {
52    /// Construct from an existing pool. The caller must have already run
53    /// [`run_migrations`] on the pool before issuing any store operations.
54    #[must_use]
55    pub fn new(pool: sqlx::SqlitePool) -> Self {
56        Self { pool }
57    }
58
59    /// Borrow the underlying pool (e.g. to run custom queries alongside codlet).
60    #[must_use]
61    pub fn pool(&self) -> &sqlx::SqlitePool {
62        &self.pool
63    }
64}