use async_trait::async_trait;
use floxide_core::*;
use floxide_macros::workflow;
use std::time::Duration;
use tokio::time::sleep;
#[derive(Clone, Debug)]
pub struct SlowNode {
dur: Duration,
}
#[async_trait]
impl Node for SlowNode {
type Input = ();
type Output = ();
async fn process(
&self,
_ctx: &(),
_input: (),
) -> Result<Transition<Self::Output>, FloxideError> {
println!("SlowNode: sleeping for {:?}", self.dur);
sleep(self.dur).await;
println!("SlowNode: woke up");
Ok(Transition::Next(()))
}
}
workflow! {
pub struct TimeoutWorkflow {
slow: SlowNode,
}
context = ();
start = slow;
edges {
slow => {};
}
}
pub async fn run_timeout_workflow() -> Result<bool, Box<dyn std::error::Error>> {
let wf = TimeoutWorkflow {
slow: SlowNode {
dur: Duration::from_secs(2),
},
};
let mut ctx = WorkflowCtx::new(());
ctx.set_timeout(Duration::from_millis(500));
match wf.run(&ctx, ()).await {
Ok(_) => Ok(false), Err(_e) => Ok(true), }
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.init();
let timed_out = run_timeout_workflow().await?;
if timed_out {
println!("Workflow failed due to timeout");
} else {
println!("Workflow completed successfully");
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_timeout_workflow() {
let timed_out = run_timeout_workflow().await.expect("should run workflow");
assert!(timed_out, "Workflow should time out");
}
}