75b183077f
Switching a brand-new DB file to WAL is a one-time file-level change; letting multiple pooled connections perform it concurrently during warm-up races the switch and can surface a spurious lock (observed as intermittent 500s under the integration harness). Open ONE connection to establish WAL before the pool opens, so every pooled connection thereafter only re-asserts an already-WAL file. Keeps per-connection foreign_keys + busy_timeout.
46 lines
1.7 KiB
Rust
46 lines
1.7 KiB
Rust
use anyhow::Result;
|
|
use sqlx::{
|
|
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions},
|
|
ConnectOptions, Connection, SqlitePool,
|
|
};
|
|
use std::str::FromStr;
|
|
use std::time::Duration;
|
|
use tracing::info;
|
|
|
|
pub type Pool = SqlitePool;
|
|
|
|
pub async fn init_pool(database_url: &str, max_connections: u32) -> Result<Pool> {
|
|
info!("Connecting to database: {}", database_url);
|
|
// Per-connection options so EVERY pooled connection gets them: WAL for
|
|
// reader/writer concurrency, foreign keys on, and a busy_timeout so a
|
|
// transient SQLITE_BUSY under concurrent access waits-and-retries.
|
|
let opts = SqliteConnectOptions::from_str(database_url)?
|
|
.create_if_missing(true)
|
|
.journal_mode(SqliteJournalMode::Wal)
|
|
.foreign_keys(true)
|
|
.busy_timeout(Duration::from_secs(5));
|
|
// Establish WAL on the file via ONE connection BEFORE the pool opens.
|
|
// Switching a fresh DB to WAL is a one-time file-level change; letting
|
|
// several pooled connections do it concurrently at warm-up races that
|
|
// switch and can surface a spurious lock. Serialize it here so every
|
|
// pooled connection thereafter only re-asserts an already-WAL file.
|
|
{
|
|
let mut conn = opts.clone().connect().await?;
|
|
sqlx::query("PRAGMA journal_mode=WAL")
|
|
.execute(&mut conn)
|
|
.await?;
|
|
conn.close().await?;
|
|
}
|
|
let pool = SqlitePoolOptions::new()
|
|
.max_connections(max_connections)
|
|
.connect_with(opts)
|
|
.await?;
|
|
Ok(pool)
|
|
}
|
|
|
|
pub async fn run_migrations(pool: &Pool) -> Result<()> {
|
|
info!("Running database migrations");
|
|
sqlx::migrate!("./migrations").run(pool).await?;
|
|
Ok(())
|
|
}
|