oxedyne/fe2o3/fe2o3_datime/tests/real_time_scheduler_demo.rs
8.6 KiB, 43 runs
created by r1870400018:8656, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download ยท who wrote it ยท its history
| 1 | //! Demonstration of the real-time scheduling system with background processing |
| 2 | //! |
| 3 | //! [Written with AI entirely](https://need2know.ai/entirely-ai/code)\ |
| 4 | //! Anthropic Claude |
| 5 | |
| 6 | use oxedyne_fe2o3_core::prelude::*; |
| 7 | use oxedyne_fe2o3_datime::{ |
| 8 | schedule::{Scheduler, SchedulerConfig, Task, TaskPriority}, |
| 9 | schedule::action::CallbackAction, |
| 10 | time::CalClockZone, |
| 11 | }; |
| 12 | use std::time::Duration; |
| 13 | use std::sync::{Arc, Mutex}; |
| 14 | |
| 15 | #[test] |
| 16 | fn test_real_time_scheduler_demo() -> Outcome<()> { |
| 17 | println!("=== Real-Time Scheduling System Demo ==="); |
| 18 | |
| 19 | // Create a scheduler with custom configuration |
| 20 | let config = SchedulerConfig { |
| 21 | max_concurrent_tasks: 5, |
| 22 | check_interval_millis: 100, // Check every 100ms for demo |
| 23 | continue_on_failure: true, |
| 24 | queue_size: 100, |
| 25 | worker_threads: 2, |
| 26 | enable_background_processing: true, |
| 27 | }; |
| 28 | |
| 29 | let mut scheduler = Scheduler::with_config(config); |
| 30 | |
| 31 | // Start the background processing system |
| 32 | res!(scheduler.start()); |
| 33 | println!("โ Background processing system started"); |
| 34 | |
| 35 | // Create a shared counter to track task executions |
| 36 | let counter = Arc::new(Mutex::new(0)); |
| 37 | |
| 38 | // Schedule several tasks with different priorities |
| 39 | let zone = CalClockZone::utc(); |
| 40 | |
| 41 | // High priority task |
| 42 | let counter_clone = Arc::clone(&counter); |
| 43 | let high_priority_task = ok!(Task::new("high_priority_task", zone.clone()) |
| 44 | .at_time(0, 0, 0) // Execute immediately |
| 45 | .on_date(2024, 1, 1) |
| 46 | .priority(TaskPriority::High) |
| 47 | .with_action(CallbackAction::with_description( |
| 48 | move || { |
| 49 | let mut count = counter_clone.lock().unwrap(); |
| 50 | *count += 1; |
| 51 | println!("๐ฅ High priority task executed! Counter: {}", *count); |
| 52 | Ok(()) |
| 53 | }, |
| 54 | "High priority demonstration task" |
| 55 | )) |
| 56 | .build()); |
| 57 | |
| 58 | // Normal priority task |
| 59 | let counter_clone = Arc::clone(&counter); |
| 60 | let normal_priority_task = ok!(Task::new("normal_priority_task", zone.clone()) |
| 61 | .at_time(0, 0, 0) // Execute immediately |
| 62 | .on_date(2024, 1, 1) |
| 63 | .priority(TaskPriority::Normal) |
| 64 | .with_action(CallbackAction::with_description( |
| 65 | move || { |
| 66 | let mut count = counter_clone.lock().unwrap(); |
| 67 | *count += 10; |
| 68 | println!("๐ Normal priority task executed! Counter: {}", *count); |
| 69 | Ok(()) |
| 70 | }, |
| 71 | "Normal priority demonstration task" |
| 72 | )) |
| 73 | .build()); |
| 74 | |
| 75 | // Critical priority task |
| 76 | let counter_clone = Arc::clone(&counter); |
| 77 | let critical_priority_task = ok!(Task::new("critical_priority_task", zone.clone()) |
| 78 | .at_time(0, 0, 0) // Execute immediately |
| 79 | .on_date(2024, 1, 1) |
| 80 | .priority(TaskPriority::Critical) |
| 81 | .with_action(CallbackAction::with_description( |
| 82 | move || { |
| 83 | let mut count = counter_clone.lock().unwrap(); |
| 84 | *count += 100; |
| 85 | println!("๐จ Critical priority task executed! Counter: {}", *count); |
| 86 | Ok(()) |
| 87 | }, |
| 88 | "Critical priority demonstration task" |
| 89 | )) |
| 90 | .build()); |
| 91 | |
| 92 | // Schedule all tasks |
| 93 | let task1_id = res!(scheduler.schedule(high_priority_task)); |
| 94 | let task2_id = res!(scheduler.schedule(normal_priority_task)); |
| 95 | let task3_id = res!(scheduler.schedule(critical_priority_task)); |
| 96 | |
| 97 | println!("๐ Scheduled 3 tasks:"); |
| 98 | println!(" - Task 1 (High Priority): {}", task1_id); |
| 99 | println!(" - Task 2 (Normal Priority): {}", task2_id); |
| 100 | println!(" - Task 3 (Critical Priority): {}", task3_id); |
| 101 | |
| 102 | // Give the scheduler time to process tasks |
| 103 | println!("โณ Waiting for tasks to execute..."); |
| 104 | std::thread::sleep(Duration::from_millis(2000)); |
| 105 | |
| 106 | // Check scheduler statistics |
| 107 | let stats = scheduler.stats(); |
| 108 | println!("\n๐ Scheduler Statistics:"); |
| 109 | println!(" - Scheduled tasks: {}", stats.scheduled_tasks); |
| 110 | println!(" - Running tasks: {}", stats.running_tasks); |
| 111 | println!(" - Queued tasks: {}", stats.queued_tasks); |
| 112 | println!(" - Completed tasks: {}", stats.completed_tasks); |
| 113 | println!(" - Failed tasks: {}", stats.failed_tasks); |
| 114 | println!(" - Average execution time: {}ms", stats.avg_execution_time_millis); |
| 115 | println!(" - Uptime: {}s", stats.uptime_seconds); |
| 116 | |
| 117 | // Check the final counter value |
| 118 | let final_count = *counter.lock().unwrap(); |
| 119 | println!("\n๐ฏ Final counter value: {}", final_count); |
| 120 | |
| 121 | // Stop the scheduler |
| 122 | res!(scheduler.stop()); |
| 123 | println!("๐ Background processing system stopped"); |
| 124 | |
| 125 | // Verify that all tasks executed (counter should be 111: 1 + 10 + 100) |
| 126 | if final_count == 111 { |
| 127 | println!("โ All tasks executed successfully in priority order!"); |
| 128 | } else { |
| 129 | println!("โ ๏ธ Task execution count unexpected: {}", final_count); |
| 130 | } |
| 131 | |
| 132 | // Verify scheduler stats show completed tasks |
| 133 | assert!(stats.completed_tasks >= 3, "Expected at least 3 completed tasks, got {}", stats.completed_tasks); |
| 134 | assert_eq!(stats.failed_tasks, 0, "Expected no failed tasks, got {}", stats.failed_tasks); |
| 135 | |
| 136 | println!("\n๐ Real-time scheduling system demonstration completed successfully!"); |
| 137 | |
| 138 | Ok(()) |
| 139 | } |
| 140 | |
| 141 | #[test] |
| 142 | fn test_scheduler_queue_management() -> Outcome<()> { |
| 143 | println!("=== Task Queue Management Test ==="); |
| 144 | |
| 145 | // Create scheduler with small queue for testing limits |
| 146 | let config = SchedulerConfig { |
| 147 | queue_size: 2, |
| 148 | worker_threads: 1, |
| 149 | enable_background_processing: false, // Manual processing for predictable testing |
| 150 | ..Default::default() |
| 151 | }; |
| 152 | |
| 153 | let mut scheduler = Scheduler::with_config(config); |
| 154 | let zone = CalClockZone::utc(); |
| 155 | |
| 156 | // Create test tasks |
| 157 | let task1 = ok!(Task::new("task1", zone.clone()) |
| 158 | .at_time(12, 0, 0) |
| 159 | .on_date(2024, 6, 15) |
| 160 | .with_action(CallbackAction::new(|| { |
| 161 | println!("Task 1 executed"); |
| 162 | Ok(()) |
| 163 | })) |
| 164 | .build()); |
| 165 | |
| 166 | let task2 = ok!(Task::new("task2", zone.clone()) |
| 167 | .at_time(12, 0, 0) |
| 168 | .on_date(2024, 6, 15) |
| 169 | .with_action(CallbackAction::new(|| { |
| 170 | println!("Task 2 executed"); |
| 171 | Ok(()) |
| 172 | })) |
| 173 | .build()); |
| 174 | |
| 175 | let task3 = ok!(Task::new("task3", zone.clone()) |
| 176 | .at_time(12, 0, 0) |
| 177 | .on_date(2024, 6, 15) |
| 178 | .with_action(CallbackAction::new(|| { |
| 179 | println!("Task 3 executed"); |
| 180 | Ok(()) |
| 181 | })) |
| 182 | .build()); |
| 183 | |
| 184 | // Schedule tasks up to queue limit |
| 185 | res!(scheduler.schedule(task1)); |
| 186 | res!(scheduler.schedule(task2)); |
| 187 | |
| 188 | // Try to schedule one more task - should succeed since queue_size is 2 |
| 189 | res!(scheduler.schedule(task3)); |
| 190 | |
| 191 | let stats = scheduler.stats(); |
| 192 | println!("๐ Scheduled {} tasks", stats.scheduled_tasks); |
| 193 | |
| 194 | assert_eq!(stats.scheduled_tasks, 3); |
| 195 | |
| 196 | println!("โ Queue management test completed successfully!"); |
| 197 | |
| 198 | Ok(()) |
| 199 | } |
| 200 | |
| 201 | #[test] |
| 202 | fn test_task_priority_ordering() -> Outcome<()> { |
| 203 | println!("=== Task Priority Ordering Test ==="); |
| 204 | |
| 205 | let mut scheduler = Scheduler::new(); |
| 206 | let zone = CalClockZone::utc(); |
| 207 | |
| 208 | // Create tasks with different priorities |
| 209 | let low_task = ok!(Task::new("low_priority", zone.clone()) |
| 210 | .at_time(0, 0, 0) |
| 211 | .on_date(2024, 1, 1) |
| 212 | .priority(TaskPriority::Low) |
| 213 | .with_action(CallbackAction::new(|| { |
| 214 | println!("๐ฝ Low priority task"); |
| 215 | Ok(()) |
| 216 | })) |
| 217 | .build()); |
| 218 | |
| 219 | let critical_task = ok!(Task::new("critical_priority", zone.clone()) |
| 220 | .at_time(0, 0, 0) |
| 221 | .on_date(2024, 1, 1) |
| 222 | .priority(TaskPriority::Critical) |
| 223 | .with_action(CallbackAction::new(|| { |
| 224 | println!("๐บ Critical priority task"); |
| 225 | Ok(()) |
| 226 | })) |
| 227 | .build()); |
| 228 | |
| 229 | let normal_task = ok!(Task::new("normal_priority", zone.clone()) |
| 230 | .at_time(0, 0, 0) |
| 231 | .on_date(2024, 1, 1) |
| 232 | .priority(TaskPriority::Normal) |
| 233 | .with_action(CallbackAction::new(|| { |
| 234 | println!("๐ Normal priority task"); |
| 235 | Ok(()) |
| 236 | })) |
| 237 | .build()); |
| 238 | |
| 239 | // Schedule in non-priority order to test queue ordering |
| 240 | res!(scheduler.schedule(low_task)); |
| 241 | res!(scheduler.schedule(critical_task)); |
| 242 | res!(scheduler.schedule(normal_task)); |
| 243 | |
| 244 | println!("๐ Scheduled tasks in order: Low, Critical, Normal"); |
| 245 | println!("๐ฏ Priority queue should reorder them as: Critical, Normal, Low"); |
| 246 | |
| 247 | let stats = scheduler.stats(); |
| 248 | assert_eq!(stats.scheduled_tasks, 3); |
| 249 | |
| 250 | println!("โ Task priority ordering test completed successfully!"); |
| 251 | |
| 252 | Ok(()) |
| 253 | } |