Skip to main content

timeout/
timeout.rs

1//! Timeout Policy Example
2//!
3//! This example demonstrates the TimeoutPolicy which enforces
4//! time-bounded operations.
5
6use do_over::{error::DoOverError, policy::Policy, timeout::TimeoutPolicy};
7use std::time::{Duration, Instant};
8
9#[tokio::main]
10async fn main() {
11    println!("=== Do-Over Timeout Policy Example ===\n");
12
13    // Scenario 1: Fast operation completes within timeout
14    fast_operation_example().await;
15
16    println!("\n{}\n", "─".repeat(60));
17
18    // Scenario 2: Slow operation exceeds timeout
19    slow_operation_example().await;
20
21    println!("\n{}\n", "─".repeat(60));
22
23    // Scenario 3: Edge case - operation completes just before timeout
24    edge_case_example().await;
25}
26
27async fn fast_operation_example() {
28    println!("📌 Scenario 1: Fast Operation (completes within timeout)");
29    println!("   Configuration: timeout=500ms, operation_time=100ms\n");
30
31    let policy = TimeoutPolicy::new(Duration::from_millis(500));
32    let start = Instant::now();
33
34    let result: Result<String, DoOverError<String>> = policy
35        .execute(|| async {
36            println!("   → Operation started...");
37            tokio::time::sleep(Duration::from_millis(100)).await;
38            println!("   → Operation completed!");
39            Ok("Fast operation result".to_string())
40        })
41        .await;
42
43    let elapsed = start.elapsed();
44    println!("\n   Result: {:?}", result.unwrap());
45    println!("   Elapsed: {:?} (well under 500ms timeout)", elapsed);
46}
47
48async fn slow_operation_example() {
49    println!("📌 Scenario 2: Slow Operation (exceeds timeout)");
50    println!("   Configuration: timeout=200ms, operation_time=500ms\n");
51
52    let policy = TimeoutPolicy::new(Duration::from_millis(200));
53    let start = Instant::now();
54
55    let result: Result<String, DoOverError<String>> = policy
56        .execute(|| async {
57            println!("   → Operation started (will take 500ms)...");
58            tokio::time::sleep(Duration::from_millis(500)).await;
59            // This line should not be reached
60            println!("   → This should not print!");
61            Ok("Slow operation result".to_string())
62        })
63        .await;
64
65    let elapsed = start.elapsed();
66
67    match result {
68        Err(DoOverError::Timeout) => {
69            println!("   → Operation cancelled due to timeout!");
70            println!("\n   Result: DoOverError::Timeout");
71        }
72        _ => println!("   Unexpected result: {:?}", result),
73    }
74
75    println!("   Elapsed: {:?} (stopped at ~200ms timeout)", elapsed);
76    println!("\n   💡 The operation was cancelled - no resources wasted!");
77}
78
79async fn edge_case_example() {
80    println!("📌 Scenario 3: Edge Case (operation completes just in time)");
81    println!("   Configuration: timeout=300ms, operation_time=250ms\n");
82
83    let policy = TimeoutPolicy::new(Duration::from_millis(300));
84    let start = Instant::now();
85
86    let result: Result<String, DoOverError<String>> = policy
87        .execute(|| async {
88            println!("   → Operation started (will take 250ms)...");
89            tokio::time::sleep(Duration::from_millis(250)).await;
90            println!("   → Operation completed just in time!");
91            Ok("Completed with 50ms to spare".to_string())
92        })
93        .await;
94
95    let elapsed = start.elapsed();
96
97    match result {
98        Ok(msg) => {
99            println!("\n   Result: ✅ {}", msg);
100        }
101        Err(DoOverError::Timeout) => {
102            println!("\n   Result: ❌ Timeout (race condition)");
103        }
104        Err(e) => {
105            println!("\n   Result: {:?}", e);
106        }
107    }
108
109    println!("   Elapsed: {:?}", elapsed);
110}