This directory contains complete, runnable examples that demonstrate how to use Duroxide for various orchestration patterns. These examples are designed to be the first place LLMs and developers look when learning how to use Duroxide.
Start here if you're confused about timers vs activities!
cargo run --example delays_and_timeoutsWhat you'll learn:
- ✅ CORRECT: Use
ctx.schedule_timer()for orchestration delays and timeouts - ✅ CORRECT: Use
ctx.select2()for timeout patterns - ✅ CORRECT: Activities can use any async operations (sleep, HTTP, DB, etc.)
- The key rule: Orchestrations = deterministic, Activities = any async work
Basic orchestration setup and execution.
cargo run --example hello_worldWhat you'll learn:
- Setting up a basic orchestration with activities
- Using the SQLite provider for persistence
- Running orchestrations with the in-process runtime
- Basic error handling and completion waiting
Parallel processing pattern for handling multiple items concurrently.
cargo run --example fan_out_fan_inWhat you'll learn:
- Scheduling multiple activities in parallel
- Using
ctx.join()for deterministic result aggregation - Typed activity inputs and outputs with Serde
- Processing collections of data efficiently
Human-in-the-loop workflows with timeouts and external approvals.
cargo run --example timers_and_eventsWhat you'll learn:
- Using durable timers for delays and timeouts
- Waiting for external events (approvals, webhooks)
- Race conditions with
ctx.select2() - Building approval workflows
Sequential operations where each step depends on the previous result:
async fn chain_example(ctx: OrchestrationContext) -> Result<String, String> {
let step1 = ctx.schedule_activity("Step1", "input").await?;
let step2 = ctx.schedule_activity("Step2", &step1).await?;
let step3 = ctx.schedule_activity("Step3", &step2).await?;
Ok(step3)
}Rollback operations on failure:
async fn saga_example(ctx: OrchestrationContext) -> Result<String, String> {
let result1 = ctx.schedule_activity("ReserveInventory", "item1").await?;
match ctx.schedule_activity("ProcessPayment", "card123").await {
Ok(payment) => {
ctx.schedule_activity("ShipItem", &result1).await?;
Ok("Order completed".to_string())
}
Err(e) => {
// Compensate: release inventory
ctx.schedule_activity("ReleaseInventory", &result1).await?;
Err(format!("Payment failed, inventory released: {}", e))
}
}
}Breaking complex workflows into smaller, reusable orchestrations:
async fn parent_orchestration(ctx: OrchestrationContext) -> Result<String, String> {
// Start multiple sub-orchestrations
let sub1 = ctx.schedule_sub_orchestration("ProcessOrder", "order1");
let sub2 = ctx.schedule_sub_orchestration("ProcessOrder", "order2");
// Wait for all to complete
let results = ctx.join(vec![sub1, sub2]).await;
// Aggregate results - each result is Result<String, String>
let success_count = results.iter().filter(|r| r.is_ok()).count();
Ok(format!("Processed {} orders successfully", success_count))
}- Reserve inventory → Process payment → Ship item → Send confirmation
- Compensation: Release inventory if payment fails
- Submit document → Notify approvers → Wait for approval → Archive
- Timeout handling: Send reminders, escalate after delays
- Fan-out: Process multiple files in parallel
- Fan-in: Aggregate results and generate reports
- Error handling: Retry failed items, continue with successful ones
- Provision infrastructure → Configure services → Run health checks → Notify completion
- Rollback: Clean up resources if any step fails
- Keep activities stateless and idempotent
- Use meaningful activity names
- Handle errors gracefully within activities
- Keep orchestrations deterministic (no random numbers, current time, etc.)
- Use
ctx.trace_*for logging instead ofprintln! - Handle all possible error cases
- Use
Result<String, String>for activity outputs - Implement compensation logic for critical operations
- Use timeouts to prevent hanging orchestrations
- Use fan-out/fan-in for parallel processing
- Consider sub-orchestrations for complex workflows
- Use appropriate timeout values
All examples can be run with:
# Run a specific example
cargo run --example hello_world
# Run with logging
RUST_LOG=debug cargo run --example fan_out_fan_in
# Run all examples (if you have a script)
for example in hello_world fan_out_fan_in timers_and_events; do
echo "Running $example..."
cargo run --example $example
doneAfter running these examples:
- Read the documentation: Check
docs/ORCHESTRATION-GUIDE.mdfor the complete guide - Explore the test suite: Look at
tests/e2e_samples.rsfor more complex scenarios - Build your own: Start with a simple orchestration and gradually add complexity
- Join the community: This is an experimental project - contributions welcome!
- "Activity not found": Make sure you've registered the activity in the
ActivityRegistry - "Orchestration not found": Ensure the orchestration is registered in the
OrchestrationRegistry - Timeout errors: Increase timeout values or check if external events are being raised
- Compilation errors: Make sure you're using the latest version of Duroxide
- Check the main README.md for overview information
- Look at the test files for working examples
- Review the architecture documentation in
docs/ - Open an issue if you find bugs or need help