use anyhow::Result; use sqlx::SqlitePool; use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions}; use std::path::Path; use std::str::FromStr; use std::time::Duration; pub async fn connect(path: &Path) -> Result { let url = format!("sqlite://{}?mode=rwc", path.display()); let opts = SqliteConnectOptions::from_str(&url)? .create_if_missing(true) .foreign_keys(true) // WAL lets readers run concurrently with a writer; busy_timeout makes a // second writer wait for the lock instead of erroring out as SQLITE_BUSY // (which surfaced as a 500 to the operator mid-deploy — ultra-fuzz Run 2). .journal_mode(SqliteJournalMode::Wal) .busy_timeout(Duration::from_secs(5)); let pool = SqlitePoolOptions::new() .max_connections(4) .connect_with(opts) .await?; Ok(pool) } pub async fn migrate(pool: &SqlitePool) -> Result<()> { sqlx::migrate!("./migrations").run(pool).await?; Ok(()) }