Skip to main content

codlet_sqlx/
lib.rs

1//! SQLite and PostgreSQL storage adapters for codlet (RFC-011, RFC-034).
2//!
3//! ## Backends
4//!
5//! | Feature | Type | Connection | Use case |
6//! |---------|------|-----------|----------|
7//! | `sqlite` (default) | `SqliteStore` | `"sqlite::memory:"`, `"sqlite:path/to/db"` | Local dev, single-server |
8//! | `postgres` | `PostgresStore` | `postgres://…` | Multi-instance production |
9//!
10//! Both stores implement `CodeStore + SessionStore + FormTokenStore +
11//! CodeAdminStore` and pass the full `codlet-conformance` suite.
12//!
13//! ## Atomicity guarantee
14//!
15//! Every one-time transition (code claim, form-token consume) uses a single
16//! `UPDATE … WHERE … AND <guard>` checked via `rows_affected()`. For
17//! PostgreSQL, `READ COMMITTED` isolation + row-level locking means concurrent
18//! updates serialise at the row — exactly one wins. No `SERIALIZABLE`
19//! isolation or `RETURNING` clause is needed or used (RFC-034 §7).
20//!
21//! ## Conformance
22//!
23//! All stores pass the `codlet-conformance` suite including the concurrent
24//! claim race test (RFC-022, RFC-023).
25
26#![forbid(unsafe_code)]
27
28pub mod admin;
29pub mod code;
30pub mod migration;
31pub mod session;
32pub mod token;
33
34#[cfg(feature = "postgres")]
35pub mod postgres;
36
37pub use migration::run_migrations;
38
39#[cfg(feature = "postgres")]
40pub use postgres::{PostgresStore, run_postgres_migrations};
41
42/// A handle wrapping a [`sqlx::SqlitePool`] that implements all codlet
43/// store traits (RFC-011).
44///
45/// Clone is cheap (the pool is reference-counted internally).
46#[derive(Debug, Clone)]
47pub struct SqliteStore {
48    pub(crate) pool: sqlx::SqlitePool,
49}
50
51impl SqliteStore {
52    /// Construct from an existing pool.
53    ///
54    /// Call [`run_migrations`] on the pool before issuing any store
55    /// operations.
56    #[must_use]
57    pub fn new(pool: sqlx::SqlitePool) -> Self {
58        Self { pool }
59    }
60
61    /// Borrow the underlying pool.
62    #[must_use]
63    pub fn pool(&self) -> &sqlx::SqlitePool {
64        &self.pool
65    }
66}