Skip to main content

chronon_backend_sqlite/
lib.rs

1//! `SQLite` [`SchedulerStore`](chronon_core::store::SchedulerStore) for Chronon.
2//!
3//! **Audience:** backend engineers and test authors needing embedded, file-backed persistence.
4//!
5//! ## Stack position
6//!
7//! ```text
8//! chronon (facade, `sqlite` feature) → chronon-backend-sqlite → chronon-backend-sql-common → chronon-core
9//! ```
10//!
11//! Suitable for single-process deployments and CI. SQLite allows one writer at a time;
12//! use PostgreSQL or the Redis composite backend for multi-worker claim throughput.
13//!
14//! ## Entry points
15//!
16//! - [`SqliteSchedulerStore::new`] — open a database file
17//! - [`SqliteSchedulerStore::connect`] — connect via URL (including `:memory:`)
18//!
19//! ## Example
20//!
21//! ```rust,no_run
22//! use chronon_backend_sqlite::SqliteSchedulerStore;
23//!
24//! # async fn example() -> chronon_core::Result<()> {
25//! let store = SqliteSchedulerStore::connect("sqlite://:memory:").await?;
26//! # Ok(())
27//! # }
28//! ```
29
30use std::path::Path;
31
32use chronon_backend_sql_common::SqlSchedulerStore;
33use chronon_core::Result;
34use sqlx::SqlitePool;
35
36/// SQLite-backed scheduler store.
37pub struct SqliteSchedulerStore {
38    inner: SqlSchedulerStore,
39}
40
41impl SqliteSchedulerStore {
42    /// Open a `SQLite` database at `path` (creates the file if missing).
43    ///
44    /// # Examples
45    ///
46    /// ```rust,no_run
47    /// use chronon_backend_sqlite::SqliteSchedulerStore;
48    ///
49    /// # async fn example() -> chronon_core::Result<()> {
50    /// let store = SqliteSchedulerStore::new("/var/lib/chronon/chronon.db").await?;
51    /// # Ok(())
52    /// # }
53    /// ```
54    ///
55    /// # Errors
56    ///
57    /// Returns a storage error when the database cannot be opened or schema bootstrap fails.
58    pub async fn new(path: impl AsRef<Path>) -> Result<Self> {
59        let url = format!("sqlite://{}?mode=rwc", path.as_ref().display());
60        Self::connect(&url).await
61    }
62
63    /// Connect using a `SQLite` connection URL.
64    ///
65    /// # Examples
66    ///
67    /// ```rust,no_run
68    /// use chronon_backend_sqlite::SqliteSchedulerStore;
69    ///
70    /// # async fn example() -> chronon_core::Result<()> {
71    /// let store = SqliteSchedulerStore::connect("sqlite://:memory:").await?;
72    /// # Ok(())
73    /// # }
74    /// ```
75    ///
76    /// # Errors
77    ///
78    /// Returns a storage error when the pool cannot connect or schema bootstrap fails.
79    pub async fn connect(url: &str) -> Result<Self> {
80        let inner = SqlSchedulerStore::connect_sqlite(url).await?;
81        Ok(Self { inner })
82    }
83
84    /// Wrap an existing pool (schema bootstrap runs).
85    ///
86    /// # Examples
87    ///
88    /// ```rust,no_run
89    /// use chronon_backend_sqlite::SqliteSchedulerStore;
90    /// use sqlx::sqlite::SqlitePoolOptions;
91    ///
92    /// # async fn example() -> chronon_core::Result<()> {
93    /// let pool = SqlitePoolOptions::new()
94    ///     .connect("sqlite://:memory:")
95    ///     .await
96    ///     .expect("pool");
97    /// let store = SqliteSchedulerStore::from_pool(pool).await?;
98    /// # Ok(())
99    /// # }
100    /// ```
101    ///
102    /// # Errors
103    ///
104    /// Returns a storage error when schema bootstrap fails.
105    pub async fn from_pool(pool: SqlitePool) -> Result<Self> {
106        let inner = SqlSchedulerStore::from_sqlite_pool(pool).await?;
107        Ok(Self { inner })
108    }
109
110    /// Underlying connection pool.
111    ///
112    /// # Panics
113    ///
114    /// Panics if the inner pool is not `SQLite` (internal invariant violation).
115    #[must_use]
116    pub fn pool(&self) -> &SqlitePool {
117        match self.inner.pool() {
118            chronon_backend_sql_common::SqlPool::Sqlite(pool) => pool,
119            chronon_backend_sql_common::SqlPool::Postgres(_) => {
120                panic!("sqlite backend has non-sqlite pool")
121            }
122        }
123    }
124}
125
126impl std::fmt::Debug for SqliteSchedulerStore {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        f.debug_struct("SqliteSchedulerStore")
129            .finish_non_exhaustive()
130    }
131}
132
133chronon_backend_sql_common::delegate_scheduler_store!(SqliteSchedulerStore, inner);