1pub mod coordinator;
36pub mod executor;
37pub mod processors;
38
39use omega_core::{
40 LoopType, CycleInput, CycleOutput, LoopManager,
41};
42use std::collections::HashMap;
43use std::error::Error;
44use std::sync::Arc;
45use tokio::sync::RwLock;
46use tracing::{info, debug};
47
48pub use coordinator::LoopCoordinator;
49pub use executor::LoopExecutor;
50
51pub struct LoopEngine {
53 coordinator: Arc<RwLock<LoopCoordinator>>,
54 executors: HashMap<LoopType, LoopExecutor>,
55 running: Arc<RwLock<bool>>,
56}
57
58impl LoopEngine {
59 pub fn new() -> Self {
61 info!("Initializing Omega Loop Engine");
62
63 let coordinator = Arc::new(RwLock::new(LoopCoordinator::new()));
64
65 let mut executors = HashMap::new();
67 for loop_type in LoopType::all_loops() {
68 executors.insert(loop_type, LoopExecutor::new(loop_type));
69 }
70
71 Self {
72 coordinator,
73 executors,
74 running: Arc::new(RwLock::new(false)),
75 }
76 }
77
78 pub async fn initialize(&mut self) -> Result<(), Box<dyn Error>> {
80 info!("Starting Loop Engine initialization");
81
82 let mut coord = self.coordinator.write().await;
83
84 for loop_type in LoopType::all_loops() {
86 let name = format!("{:?} Loop", loop_type);
87 let description = loop_type.description().to_string();
88
89 coord.create_loop(loop_type, name, description).await?;
90 debug!("Created {:?} loop", loop_type);
91 }
92
93 *self.running.write().await = true;
94 info!("Loop Engine initialized with {} loops", LoopType::all_loops().len());
95
96 Ok(())
97 }
98
99 pub async fn shutdown(&mut self) -> Result<(), Box<dyn Error>> {
101 info!("Shutting down Loop Engine");
102
103 *self.running.write().await = false;
104
105 for (loop_type, executor) in &mut self.executors {
107 executor.stop().await?;
108 debug!("Stopped {:?} executor", loop_type);
109 }
110
111 info!("Loop Engine shutdown complete");
112 Ok(())
113 }
114
115 pub async fn is_running(&self) -> bool {
117 *self.running.read().await
118 }
119
120 pub async fn execute_cycle(
122 &mut self,
123 loop_type: LoopType,
124 input: CycleInput,
125 ) -> Result<CycleOutput, Box<dyn Error>> {
126 if let Some(executor) = self.executors.get_mut(&loop_type) {
127 let coord = self.coordinator.clone();
128 executor.execute_cycle(coord, input).await
129 } else {
130 Err(format!("No executor found for loop type {:?}", loop_type).into())
131 }
132 }
133
134 pub fn coordinator(&self) -> Arc<RwLock<LoopCoordinator>> {
136 self.coordinator.clone()
137 }
138
139 pub async fn get_stats(&self) -> HashMap<LoopType, LoopStats> {
141 let mut stats = HashMap::new();
142 let coord = self.coordinator.read().await;
143
144 for loop_type in LoopType::all_loops() {
145 if let Ok(Some(loop_data)) = coord.get_loop_by_type(loop_type).await {
146 stats.insert(loop_type, LoopStats {
147 cycles_completed: loop_data.metrics.cycles_completed,
148 success_rate: loop_data.metrics.success_rate,
149 average_cycle_time: loop_data.metrics.average_cycle_time,
150 });
151 }
152 }
153
154 stats
155 }
156}
157
158impl Default for LoopEngine {
159 fn default() -> Self {
160 Self::new()
161 }
162}
163
164#[derive(Debug, Clone)]
166pub struct LoopStats {
167 pub cycles_completed: u64,
168 pub success_rate: f64,
169 pub average_cycle_time: chrono::Duration,
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175
176 #[tokio::test]
177 async fn test_loop_engine_initialization() {
178 let mut engine = LoopEngine::new();
179 assert!(!engine.is_running().await);
180
181 engine.initialize().await.unwrap();
182 assert!(engine.is_running().await);
183
184 engine.shutdown().await.unwrap();
185 assert!(!engine.is_running().await);
186 }
187
188 #[tokio::test]
189 async fn test_all_loops_created() {
190 let mut engine = LoopEngine::new();
191 engine.initialize().await.unwrap();
192
193 let stats = engine.get_stats().await;
194 assert_eq!(stats.len(), 7);
195
196 engine.shutdown().await.unwrap();
197 }
198}