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:
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user