fix(db): per-connection sqlite pragmas + busy_timeout

Set journal_mode=WAL, foreign_keys, and a 5s busy_timeout on the connection
options so EVERY pooled connection gets them. Previously WAL/foreign_keys were
set by a one-off PRAGMA on the pool (configuring only whichever connection
served that query), and no busy_timeout was set — so under concurrent access a
transient SQLITE_BUSY failed the transaction (surfaced as a 500 database error)
instead of waiting. This makes economy transactions robust under concurrency.
This commit is contained in:
OpenFUT Agent
2026-08-13 19:55:13 +00:00
parent bcc4f5104a
commit 0360135322
+12 -6
View File
@@ -1,24 +1,30 @@
use anyhow::Result; use anyhow::Result;
use sqlx::{ use sqlx::{
sqlite::{SqliteConnectOptions, SqlitePoolOptions}, sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions},
SqlitePool, SqlitePool,
}; };
use std::str::FromStr; use std::str::FromStr;
use std::time::Duration;
use tracing::info; use tracing::info;
pub type Pool = SqlitePool; pub type Pool = SqlitePool;
pub async fn init_pool(database_url: &str, max_connections: u32) -> Result<Pool> { pub async fn init_pool(database_url: &str, max_connections: u32) -> Result<Pool> {
info!("Connecting to database: {}", database_url); info!("Connecting to database: {}", database_url);
let opts = SqliteConnectOptions::from_str(database_url)?.create_if_missing(true); // Per-connection options so EVERY pooled connection gets them (a one-off
// `PRAGMA` on the pool only configures whichever connection served it):
// WAL for reader/writer concurrency, foreign keys on, and a busy_timeout so
// a transient SQLITE_BUSY under concurrent access waits-and-retries instead
// of failing the transaction.
let opts = SqliteConnectOptions::from_str(database_url)?
.create_if_missing(true)
.journal_mode(SqliteJournalMode::Wal)
.foreign_keys(true)
.busy_timeout(Duration::from_secs(5));
let pool = SqlitePoolOptions::new() let pool = SqlitePoolOptions::new()
.max_connections(max_connections) .max_connections(max_connections)
.connect_with(opts) .connect_with(opts)
.await?; .await?;
sqlx::query("PRAGMA journal_mode=WAL")
.execute(&pool)
.await?;
sqlx::query("PRAGMA foreign_keys=ON").execute(&pool).await?;
Ok(pool) Ok(pool)
} }