use do_over::{error::DoOverError, policy::Policy, timeout::TimeoutPolicy};
use std::time::{Duration, Instant};
#[tokio::main]
async fn main() {
println!("=== Do-Over Timeout Policy Example ===\n");
fast_operation_example().await;
println!("\n{}\n", "─".repeat(60));
slow_operation_example().await;
println!("\n{}\n", "─".repeat(60));
edge_case_example().await;
}
async fn fast_operation_example() {
println!("📌 Scenario 1: Fast Operation (completes within timeout)");
println!(" Configuration: timeout=500ms, operation_time=100ms\n");
let policy = TimeoutPolicy::new(Duration::from_millis(500));
let start = Instant::now();
let result: Result<String, DoOverError<String>> = policy
.execute(|| async {
println!(" → Operation started...");
tokio::time::sleep(Duration::from_millis(100)).await;
println!(" → Operation completed!");
Ok("Fast operation result".to_string())
})
.await;
let elapsed = start.elapsed();
println!("\n Result: {:?}", result.unwrap());
println!(" Elapsed: {:?} (well under 500ms timeout)", elapsed);
}
async fn slow_operation_example() {
println!("📌 Scenario 2: Slow Operation (exceeds timeout)");
println!(" Configuration: timeout=200ms, operation_time=500ms\n");
let policy = TimeoutPolicy::new(Duration::from_millis(200));
let start = Instant::now();
let result: Result<String, DoOverError<String>> = policy
.execute(|| async {
println!(" → Operation started (will take 500ms)...");
tokio::time::sleep(Duration::from_millis(500)).await;
println!(" → This should not print!");
Ok("Slow operation result".to_string())
})
.await;
let elapsed = start.elapsed();
match result {
Err(DoOverError::Timeout) => {
println!(" → Operation cancelled due to timeout!");
println!("\n Result: DoOverError::Timeout");
}
_ => println!(" Unexpected result: {:?}", result),
}
println!(" Elapsed: {:?} (stopped at ~200ms timeout)", elapsed);
println!("\n 💡 The operation was cancelled - no resources wasted!");
}
async fn edge_case_example() {
println!("📌 Scenario 3: Edge Case (operation completes just in time)");
println!(" Configuration: timeout=300ms, operation_time=250ms\n");
let policy = TimeoutPolicy::new(Duration::from_millis(300));
let start = Instant::now();
let result: Result<String, DoOverError<String>> = policy
.execute(|| async {
println!(" → Operation started (will take 250ms)...");
tokio::time::sleep(Duration::from_millis(250)).await;
println!(" → Operation completed just in time!");
Ok("Completed with 50ms to spare".to_string())
})
.await;
let elapsed = start.elapsed();
match result {
Ok(msg) => {
println!("\n Result: ✅ {}", msg);
}
Err(DoOverError::Timeout) => {
println!("\n Result: ❌ Timeout (race condition)");
}
Err(e) => {
println!("\n Result: {:?}", e);
}
}
println!(" Elapsed: {:?}", elapsed);
}