From 03601353228cf57cf4d9b19da85741a765ba77bb Mon Sep 17 00:00:00 2001 From: OpenFUT Agent Date: Thu, 13 Aug 2026 19:55:13 +0000 Subject: [PATCH] fix(db): per-connection sqlite pragmas + busy_timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/db.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/db.rs b/src/db.rs index 7fad7c8..26394c6 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,24 +1,30 @@ use anyhow::Result; use sqlx::{ - sqlite::{SqliteConnectOptions, SqlitePoolOptions}, + sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions}, 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 { 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() .max_connections(max_connections) .connect_with(opts) .await?; - sqlx::query("PRAGMA journal_mode=WAL") - .execute(&pool) - .await?; - sqlx::query("PRAGMA foreign_keys=ON").execute(&pool).await?; Ok(pool) }