pub trait Aux {
fn commit(self) -> bool;
fn rollback(self);
}
pub(crate) struct NoAux;
impl Aux for NoAux {
fn commit(self) -> bool {
true
}
fn rollback(self) {}
}
#[cfg(test)]
mod test {
use std::{
sync::{Arc, Mutex},
thread,
};
use crate::auxtx::*;
use crate::{
abort, atomically, atomically_aux, atomically_or_err_aux, retry, test::TestError1, TVar,
};
#[derive(Clone)]
struct TestAuxDb {
counter: Arc<Mutex<i32>>,
}
struct TestAuxTx<'a> {
db: &'a TestAuxDb,
counter: i32,
finished: bool,
}
impl TestAuxDb {
fn begin(&self) -> TestAuxTx {
let guard = self.counter.lock().unwrap();
TestAuxTx {
db: self,
counter: *guard,
finished: false,
}
}
}
impl<'a> Aux for TestAuxTx<'a> {
fn commit(mut self) -> bool {
let mut guard = self.db.counter.lock().unwrap();
*guard = self.counter;
self.finished = true;
true
}
fn rollback(mut self) {
self.finished = true;
}
}
impl Drop for TestAuxTx<'_> {
fn drop(&mut self) {
if !self.finished && !thread::panicking() {
panic!("Transaction prematurely dropped. Must call `.commit()` or `.rollback()`.");
}
}
}
impl TestAuxDb {
fn new() -> TestAuxDb {
TestAuxDb {
counter: Arc::new(Mutex::new(0)),
}
}
fn counter(&self) -> i32 {
*self.counter.lock().unwrap()
}
}
#[tokio::test]
async fn aux_commit_rollback() {
let db = TestAuxDb::new();
atomically_or_err_aux::<_, TestError1, _, _, _>(
|| db.begin(),
|atx| {
atx.counter = 1;
abort(TestError1)?;
Ok(())
},
)
.await
.expect_err("Should be aborted");
assert_eq!(db.counter(), 0);
atomically_aux(
|| db.begin(),
|atx| {
atx.counter = 1;
Ok(())
},
)
.await;
assert_eq!(db.counter(), 1);
let ta = TVar::new(42);
let dbc = db.clone();
let tac = ta.clone();
let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
let handle = tokio::spawn(async move {
atomically_aux(
|| dbc.begin(),
|atx| {
let a = tac.read()?;
atx.counter += *a;
if *a == 42 {
sender.send(()).unwrap();
retry()?;
}
Ok(())
},
)
.await;
});
let _ = receiver.recv().await;
assert_eq!(db.counter(), 1);
atomically(|| ta.write(10)).await;
handle.await.unwrap();
assert_eq!(db.counter(), 11);
}
}