use cano::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Stage {
Validate, Sanitize, Persist, Done,
}
struct ValidateTask;
#[task(state = Stage)]
impl ValidateTask {
async fn run_bare(&self) -> CanoResult<TaskResult<Stage>> {
println!("ValidateTask: checking input constraints...");
let value: i32 = 42;
if value < 0 {
return Err(CanoError::task_execution("value must be non-negative"));
}
println!(" value={value} -- OK");
Ok(TaskResult::Single(Stage::Sanitize))
}
}
struct SanitizeTask;
#[task(state = Stage)]
impl SanitizeTask {
async fn run_bare(&self) -> CanoResult<TaskResult<Stage>> {
println!("SanitizeTask: clamping value to [0, 100]...");
let raw: i32 = 42;
let clamped = raw.clamp(0, 100);
println!(" raw={raw} -> clamped={clamped}");
Ok(TaskResult::Single(Stage::Persist))
}
}
struct PersistTask;
#[task(state = Stage)]
impl PersistTask {
async fn run(&self, res: &Resources) -> CanoResult<TaskResult<Stage>> {
let store = res.get::<MemoryStore, str>("store")?;
println!("PersistTask: writing result to store...");
let result: i32 = 42_i32.clamp(0, 100);
store.put("sanitized_value", result)?;
println!(" stored sanitized_value={result}");
Ok(TaskResult::Single(Stage::Done))
}
}
#[tokio::main]
async fn main() -> CanoResult<()> {
println!("=== Bare workflow (no resources) ===\n");
let workflow = Workflow::bare()
.register(Stage::Validate, ValidateTask)
.register(Stage::Sanitize, SanitizeTask)
.add_exit_states(vec![Stage::Persist, Stage::Done]);
match workflow.orchestrate(Stage::Validate).await {
Ok(final_state) => println!("\nBare workflow reached: {final_state:?}\n"),
Err(e) => {
eprintln!("Workflow failed: {e}");
return Err(e);
}
}
println!("=== Mixed workflow (bare tasks + resource task) ===\n");
let store = MemoryStore::new();
let workflow = Workflow::new(Resources::new().insert("store", store.clone()))
.register(Stage::Validate, ValidateTask) .register(Stage::Sanitize, SanitizeTask) .register(Stage::Persist, PersistTask) .add_exit_states(vec![Stage::Done]);
match workflow.orchestrate(Stage::Validate).await {
Ok(final_state) => {
println!("\nMixed workflow reached: {final_state:?}");
if let Ok(v) = store.get::<i32>("sanitized_value") {
println!("Persisted value: {v}");
}
}
Err(e) => {
eprintln!("Workflow failed: {e}");
return Err(e);
}
}
Ok(())
}