From 07ecd4daf00207d1be5eb949befcdd556f52cf1f Mon Sep 17 00:00:00 2001 From: Sebastian Jeltsch Date: Mon, 25 Aug 2025 11:52:07 +0200 Subject: [PATCH] Simplify the acquisition of transaction locks in JS runtime. --- crates/js-runtime/src/runtime.rs | 52 +++++++++++++++++--------------- crates/sqlite/src/connection.rs | 2 +- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/crates/js-runtime/src/runtime.rs b/crates/js-runtime/src/runtime.rs index 7c09526a..f73fd315 100644 --- a/crates/js-runtime/src/runtime.rs +++ b/crates/js-runtime/src/runtime.rs @@ -451,17 +451,40 @@ self_cell!( } ); -struct OwnedLockWrapper(OwnedLock); - self_cell!( struct OwnedTransaction { - owner: MutBorrow, + owner: MutBorrow, #[covariant] dependent: Transaction, } ); +async fn new_transaction( + conn: trailbase_sqlite::Connection, +) -> Result { + for _ in 0..200 { + let Ok(lock) = OwnedLock::try_new(conn.clone(), |owner| { + return owner + .try_write_lock_for(Duration::from_micros(50)) + .ok_or("timeout"); + }) else { + tokio::time::sleep(Duration::from_micros(400)).await; + continue; + }; + + return OwnedTransaction::try_new(MutBorrow::new(lock), |owner| { + return owner + .borrow_mut() + .with_dependent_mut(|_owner, dep| dep.transaction()); + }); + } + + return Err(rusqlite::Error::ToSqlConversionFailure( + "Failed to acquire lock".into(), + )); +} + pub fn register_database_functions(handle: &RuntimeHandle, conn: trailbase_sqlite::Connection) { fn error_mapper(err: impl std::error::Error) -> rustyscript::Error { return rustyscript::Error::Runtime(err.to_string()); @@ -520,30 +543,9 @@ pub fn register_database_functions(handle: &RuntimeHandle, conn: trailbase_sqlit assert!(current_transaction_clone.lock().is_none()); let conn = conn.clone(); - let get_lock = async move || { - loop { - if let Ok(lock) = OwnedLock::try_new(conn.clone(), |owner| { - owner - .try_write_lock_for(Duration::from_micros(50)) - .ok_or("timeout") - }) { - return lock; - } - - tokio::time::sleep(Duration::from_micros(150)).await; - } - }; - let current_transaction = current_transaction_clone.clone(); return Box::pin(async move { - let lock = get_lock().await; - let tx = OwnedTransaction::try_new(MutBorrow::new(OwnedLockWrapper(lock)), |lock| { - lock - .borrow_mut() - .0 - .with_dependent_mut(|_owner, depdendent| depdendent.transaction()) - }) - .map_err(error_mapper)?; + let tx = new_transaction(conn).await.map_err(error_mapper)?; *current_transaction.lock() = Some(tx); diff --git a/crates/sqlite/src/connection.rs b/crates/sqlite/src/connection.rs index 0358b550..f647136e 100644 --- a/crates/sqlite/src/connection.rs +++ b/crates/sqlite/src/connection.rs @@ -96,7 +96,7 @@ impl Connection { }; let write_conn = new_conn()?; - let in_memory = write_conn.path().map_or(true, |s| { + let in_memory = write_conn.path().is_none_or(|s| { // Returns empty string for in-memory databases. return !s.is_empty(); });