use std::sync::Arc;
use tokio::sync::Mutex;
use super::backend::{QueryResult, TransactionOps, TxType};
use crate::error::{OrmError, Result};
pub struct TransactionContext {
inner: Arc<Mutex<Option<Box<dyn TransactionOps>>>>,
tx_type: TxType,
}
impl TransactionContext {
pub(crate) fn new(inner: Box<dyn TransactionOps>, tx_type: TxType) -> Self {
Self {
inner: Arc::new(Mutex::new(Some(inner))),
tx_type,
}
}
pub async fn query(&self, typeql: &str) -> Result<QueryResult> {
let mut guard = self.inner.lock().await;
let tx = guard
.as_mut()
.ok_or_else(|| OrmError::Transaction("Transaction already consumed".into()))?;
tx.query(typeql).await
}
pub async fn commit(&self) -> Result<()> {
let mut guard = self.inner.lock().await;
let mut tx = guard
.take()
.ok_or_else(|| OrmError::Transaction("Transaction already consumed".into()))?;
tx.commit().await
}
pub async fn rollback(&self) -> Result<()> {
let mut guard = self.inner.lock().await;
let mut tx = guard
.take()
.ok_or_else(|| OrmError::Transaction("Transaction already consumed".into()))?;
tx.rollback().await
}
pub async fn close(&self) -> Result<()> {
let mut guard = self.inner.lock().await;
let Some(mut tx) = guard.take() else {
return Ok(());
};
tx.close().await
}
pub fn tx_type(&self) -> TxType {
self.tx_type
}
}
impl Clone for TransactionContext {
fn clone(&self) -> Self {
Self {
inner: Arc::clone(&self.inner),
tx_type: self.tx_type,
}
}
}