Skip to main content

codex_state/
sqlite.rs

1//! Shared SQLite connection configuration.
2
3use codex_utils_absolute_path::AbsolutePathBuf;
4use log::LevelFilter;
5use sqlx::ConnectOptions;
6use sqlx::Error;
7use sqlx::SqlitePool;
8use sqlx::sqlite::SqliteAutoVacuum;
9use sqlx::sqlite::SqliteConnectOptions;
10use sqlx::sqlite::SqliteJournalMode;
11use sqlx::sqlite::SqlitePoolOptions;
12use sqlx::sqlite::SqliteSynchronous;
13use std::path::Path;
14use std::time::Duration;
15
16/// Resolved configuration shared by all Codex SQLite connections.
17#[derive(Clone, Debug, Eq, PartialEq)]
18pub struct SqliteConfig {
19    sqlite_home: AbsolutePathBuf,
20}
21
22impl SqliteConfig {
23    pub fn from_sqlite_home(sqlite_home: AbsolutePathBuf) -> Self {
24        Self { sqlite_home }
25    }
26
27    pub fn new_for_testing(sqlite_home: AbsolutePathBuf) -> Self {
28        Self::from_sqlite_home(sqlite_home)
29    }
30
31    pub fn home(&self) -> &Path {
32        self.sqlite_home.as_path()
33    }
34
35    /// Open a writable Codex SQLite database, creating it if necessary.
36    pub async fn open_read_write_pool(&self, path: &Path) -> Result<SqlitePool, Error> {
37        let options = SqliteConnectOptions::new()
38            .filename(path)
39            .create_if_missing(true)
40            .journal_mode(SqliteJournalMode::Wal)
41            .synchronous(SqliteSynchronous::Normal)
42            .auto_vacuum(SqliteAutoVacuum::Incremental)
43            .busy_timeout(Duration::from_secs(5))
44            .log_statements(LevelFilter::Off);
45        SqlitePoolOptions::new()
46            .max_connections(5)
47            .connect_with(options)
48            .await
49    }
50
51    /// Open an existing Codex SQLite database without creating or modifying it.
52    pub async fn open_read_only_pool(&self, path: &Path) -> Result<SqlitePool, Error> {
53        let options = SqliteConnectOptions::new()
54            .filename(path)
55            .create_if_missing(false)
56            .read_only(true)
57            .log_statements(LevelFilter::Off);
58        SqlitePoolOptions::new()
59            .max_connections(1)
60            .connect_with(options)
61            .await
62    }
63}