use dbuff::*;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;
#[derive(Debug, Clone, Default)]
struct AppData {
total: i32,
error_log: Vec<String>,
}
struct Add(i32);
#[async_trait::async_trait]
impl Command<()> for Add {
type Output = i32;
type Error = FailError;
async fn execute(self, _: ()) -> Result<Self::Output, Self::Error> {
Ok(self.0)
}
}
#[derive(Debug, Clone, wherror::Error)]
#[error(debug)]
struct FailError;
struct Fail;
#[async_trait::async_trait]
impl Command<()> for Fail {
type Output = ();
type Error = FailError;
async fn execute(self, _: ()) -> Result<Self::Output, Self::Error> {
Err(FailError)
}
}
#[tokio::main]
async fn main() {
let rt = tokio::runtime::Handle::current();
let (domain, write_handle) = SharedDomainData::with_coalesce(
AppData::default(),
Duration::from_millis(1),
);
tokio::spawn(write_handle.run());
let error_called = Arc::new(AtomicBool::new(false));
let flag = error_called.clone();
let handle = domain.bind((), rt.clone())
.on_error(move |err, d| {
flag.store(true, Ordering::SeqCst);
d.error_log.push(format!("{err}"));
})
.exec(Add(10), |d, v: &i32| d.total += *v)
.exec(Add(20), |d, v: &i32| d.total += *v)
.exec_discard(Fail)
.exec(Add(5), |d, v: &i32| d.total += *v)
.go();
let flow = handle.await.unwrap();
assert_eq!(flow, ControlFlow::Break);
tokio::time::sleep(Duration::from_millis(10)).await;
assert!(error_called.load(Ordering::SeqCst));
let guard = domain.read();
assert_eq!(guard.total, 30);
assert_eq!(guard.error_log.len(), 1);
println!("total = {}, error_log = {:?}", guard.total, guard.error_log);
}