diff --git a/Cargo.lock b/Cargo.lock index a18e27146f9..a1c0b125878 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6684,7 +6684,7 @@ dependencies = [ [[package]] name = "nym-node-status-api" -version = "3.1.0" +version = "3.1.1" dependencies = [ "ammonia", "anyhow", diff --git a/nym-node-status-api/nym-node-status-api/Cargo.toml b/nym-node-status-api/nym-node-status-api/Cargo.toml index 7e63db3672f..916f30eb1f8 100644 --- a/nym-node-status-api/nym-node-status-api/Cargo.toml +++ b/nym-node-status-api/nym-node-status-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-node-status-api" -version = "3.1.0" +version = "3.1.1" authors.workspace = true repository.workspace = true homepage.workspace = true diff --git a/nym-node-status-api/nym-node-status-api/src/cli/mod.rs b/nym-node-status-api/nym-node-status-api/src/cli/mod.rs index 0a487afe860..f150dbc1392 100644 --- a/nym-node-status-api/nym-node-status-api/src/cli/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/cli/mod.rs @@ -45,6 +45,10 @@ pub(crate) struct Cli { #[clap(long, env = "DATABASE_URL")] pub(crate) database_url: String, + #[clap(long, default_value = "5", env = "SQLX_BUSY_TIMEOUT_S")] + #[arg(value_parser = parse_duration)] + pub(crate) sqlx_busy_timeout_s: Duration, + #[clap( long, default_value = "300", diff --git a/nym-node-status-api/nym-node-status-api/src/db/mod.rs b/nym-node-status-api/nym-node-status-api/src/db/mod.rs index cc3398964c3..3f7d9449060 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/mod.rs @@ -1,10 +1,11 @@ use anyhow::{anyhow, Result}; use sqlx::{ migrate::Migrator, + query, sqlite::{SqliteAutoVacuum, SqliteConnectOptions, SqliteSynchronous}, ConnectOptions, SqlitePool, }; -use std::str::FromStr; +use std::{str::FromStr, time::Duration}; pub(crate) mod models; pub(crate) mod queries; @@ -18,9 +19,10 @@ pub(crate) struct Storage { } impl Storage { - pub async fn init(connection_url: String) -> Result { + pub async fn init(connection_url: String, busy_timeout: Duration) -> Result { let connect_options = SqliteConnectOptions::from_str(&connection_url)? .journal_mode(sqlx::sqlite::SqliteJournalMode::Wal) + .busy_timeout(busy_timeout) .synchronous(SqliteSynchronous::Normal) .auto_vacuum(SqliteAutoVacuum::Incremental) .foreign_keys(true) @@ -33,6 +35,9 @@ impl Storage { MIGRATOR.run(&pool).await?; + // aftering setting pragma, check whether it was set successfully + Self::assert_busy_timeout(pool.clone(), busy_timeout.as_secs() as i64).await?; + Ok(Storage { pool }) } @@ -40,4 +45,27 @@ impl Storage { pub fn pool_owned(&self) -> DbPool { self.pool.clone() } + + async fn assert_busy_timeout(pool: DbPool, expected_busy_timeout_s: i64) -> Result<()> { + let mut conn = pool.acquire().await?; + // Sqlite stores this value as miliseconds + // https://www.sqlite.org/pragma.html#pragma_busy_timeout + let busy_timeout_db = query!("PRAGMA busy_timeout;") + .fetch_one(conn.as_mut()) + .await?; + + let actual_busy_timeout_ms = busy_timeout_db.timeout.unwrap_or(0); + tracing::info!("PRAGMA busy_timeout={}ms", actual_busy_timeout_ms); + let expected_busy_timeout_ms = expected_busy_timeout_s * 1000; + + if expected_busy_timeout_ms != actual_busy_timeout_ms { + anyhow::bail!( + "PRAGMA busy_timeout expected: {}ms, actual: {}ms", + expected_busy_timeout_ms, + actual_busy_timeout_ms + ); + } + + Ok(()) + } } diff --git a/nym-node-status-api/nym-node-status-api/src/main.rs b/nym-node-status-api/nym-node-status-api/src/main.rs index f0bd3b5b469..7db3015a7d8 100644 --- a/nym-node-status-api/nym-node-status-api/src/main.rs +++ b/nym-node-status-api/nym-node-status-api/src/main.rs @@ -31,7 +31,7 @@ async fn main() -> anyhow::Result<()> { let connection_url = args.database_url.clone(); tracing::debug!("Using config:\n{:#?}", args); - let storage = db::Storage::init(connection_url).await?; + let storage = db::Storage::init(connection_url, args.sqlx_busy_timeout_s).await?; let db_pool = storage.pool_owned(); // Start the node scraper