Skip to content

Commit

Permalink
driver-adapters: remove dispose method for JS transaction interface
Browse files Browse the repository at this point in the history
Remove the boilerplate `Transaction.dispose` method from the public
driver adapter interface and move the corresponding functionality
directly to the destructor of `TransactionProxy`.

Refs: #4286
Closes: prisma/team-orm#391
  • Loading branch information
aqrln committed Nov 21, 2023
1 parent ba74bdf commit 222f720
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 9 deletions.
4 changes: 4 additions & 0 deletions query-engine/driver-adapters/src/async_js_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ where
.map_err(into_quaint_error)?;
js_result.into()
}

pub(crate) fn as_raw(&self) -> &ThreadsafeFunction<ArgType, ErrorStrategy::Fatal> {
&self.threadsafe_fn
}
}

impl<ArgType, ReturnType> FromNapiValue for AsyncJsFunction<ArgType, ReturnType>
Expand Down
33 changes: 24 additions & 9 deletions query-engine/driver-adapters/src/proxy.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::borrow::Cow;
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};

use crate::async_js_function::AsyncJsFunction;
use crate::conversion::JSArg;
use crate::transaction::JsTransaction;
use metrics::increment_gauge;
use napi::bindgen_prelude::{FromNapiValue, ToNapiValue};
use napi::threadsafe_function::{ErrorStrategy, ThreadsafeFunction};
use napi::{JsObject, JsString};
use napi_derive::napi;
use quaint::connector::ResultSet as QuaintResultSet;
Expand Down Expand Up @@ -52,9 +52,8 @@ pub(crate) struct TransactionProxy {
/// rollback transaction
rollback: AsyncJsFunction<(), ()>,

/// dispose transaction, cleanup logic executed at the end of the transaction lifecycle
/// on drop.
dispose: ThreadsafeFunction<(), ErrorStrategy::Fatal>,
/// whether the transaction has already been committed or rolled back
closed: AtomicBool,
}

/// This result set is more convenient to be manipulated from both Rust and NodeJS.
Expand Down Expand Up @@ -581,34 +580,50 @@ impl TransactionProxy {
pub fn new(js_transaction: &JsObject) -> napi::Result<Self> {
let commit = js_transaction.get_named_property("commit")?;
let rollback = js_transaction.get_named_property("rollback")?;
let dispose = js_transaction.get_named_property("dispose")?;
let options = js_transaction.get_named_property("options")?;

Ok(Self {
commit,
rollback,
dispose,
options,
closed: AtomicBool::new(false),
})
}

pub fn options(&self) -> &TransactionOptions {
&self.options
}

/// Commits the transaction via the driver adapter.
///
/// Cancelation safety: [`TransactionProxy::closed`] is only set after the call to JS finishes,
/// so the destructor will ensure the transaction is closed even if the future is dropped.
pub async fn commit(&self) -> quaint::Result<()> {
self.commit.call(()).await
let result = self.commit.call(()).await;
self.closed.swap(true, Ordering::Release);
result
}

/// Rolls back the transaction via the driver adapter.
///
/// Cancelation safety: [`TransactionProxy::closed`] is only set after the call to JS finishes,
/// so the destructor will ensure the transaction is closed even if the future is dropped.
pub async fn rollback(&self) -> quaint::Result<()> {
self.rollback.call(()).await
let result = self.rollback.call(()).await;
self.closed.swap(true, Ordering::Release);
result
}
}

impl Drop for TransactionProxy {
fn drop(&mut self) {
if self.closed.swap(true, Ordering::Acquire) {
return;
}

_ = self
.dispose
.rollback
.as_raw()
.call((), napi::threadsafe_function::ThreadsafeFunctionCallMode::NonBlocking);
}
}
Expand Down

0 comments on commit 222f720

Please sign in to comment.