1use crate::{CasialError, PerceptionId};
7use ahash::AHashMap;
8use anyhow::Result;
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct CoordinationMetrics {
14 pub perception_lock_latency_ms: f64,
15 pub paradox_resolution_time_ms: f64,
16 pub context_composition_time_ms: f64,
17 pub total_coordination_time_ms: f64,
18 pub memory_usage_bytes: usize,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub enum CoordinationStrategy {
24 Rapid,
26 Balanced,
28 Comprehensive,
30 Custom {
32 paradox_timeout_ms: u64,
33 perception_lock_attempts: u32,
34 synthesis_depth: u8,
35 },
36}
37
38impl Default for CoordinationStrategy {
39 fn default() -> Self {
40 Self::Balanced
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct CoordinationConfig {
47 pub strategy: CoordinationStrategy,
48 pub enable_perception_locking: bool,
49 pub enable_paradox_detection: bool,
50 pub enable_synthesis: bool,
51 pub max_coordination_time_ms: u64,
52 pub memory_limit_bytes: Option<usize>,
53}
54
55impl Default for CoordinationConfig {
56 fn default() -> Self {
57 Self {
58 strategy: CoordinationStrategy::default(),
59 enable_perception_locking: true,
60 enable_paradox_detection: true,
61 enable_synthesis: true,
62 max_coordination_time_ms: 5000, memory_limit_bytes: Some(100 * 1024 * 1024), }
65 }
66}
67
68#[derive(Debug, Clone)]
70pub struct CoordinationSession {
71 pub id: uuid::Uuid,
72 pub active_perceptions: Vec<PerceptionId>,
73 pub locked_perceptions: Vec<PerceptionId>,
74 pub detected_paradoxes: Vec<uuid::Uuid>,
75 pub start_time: std::time::Instant,
76 pub config: CoordinationConfig,
77 pub metrics: CoordinationMetrics,
78}
79
80impl CoordinationSession {
81 pub fn new(config: CoordinationConfig) -> Self {
83 Self {
84 id: uuid::Uuid::new_v4(),
85 active_perceptions: Vec::new(),
86 locked_perceptions: Vec::new(),
87 detected_paradoxes: Vec::new(),
88 start_time: std::time::Instant::now(),
89 config,
90 metrics: CoordinationMetrics {
91 perception_lock_latency_ms: 0.0,
92 paradox_resolution_time_ms: 0.0,
93 context_composition_time_ms: 0.0,
94 total_coordination_time_ms: 0.0,
95 memory_usage_bytes: 0,
96 },
97 }
98 }
99
100 pub fn add_perception(&mut self, perception_id: PerceptionId) -> Result<()> {
102 if !self.active_perceptions.contains(&perception_id) {
103 self.active_perceptions.push(perception_id);
104 }
105 Ok(())
106 }
107
108 pub fn lock_perception(&mut self, perception_id: PerceptionId) -> Result<bool> {
110 if !self.config.enable_perception_locking {
111 return Ok(false);
112 }
113
114 let lock_start = std::time::Instant::now();
115
116 let lock_acquired = !self.locked_perceptions.contains(&perception_id);
119
120 if lock_acquired {
121 self.locked_perceptions.push(perception_id);
122 }
123
124 self.metrics.perception_lock_latency_ms = lock_start.elapsed().as_secs_f64() * 1000.0;
125
126 Ok(lock_acquired)
127 }
128
129 pub fn unlock_perception(&mut self, perception_id: PerceptionId) -> Result<()> {
131 self.locked_perceptions.retain(|&id| id != perception_id);
132 Ok(())
133 }
134
135 pub fn is_timed_out(&self) -> bool {
137 self.start_time.elapsed().as_millis() > self.config.max_coordination_time_ms as u128
138 }
139
140 pub fn finalize(&mut self) {
142 self.metrics.total_coordination_time_ms = self.start_time.elapsed().as_secs_f64() * 1000.0;
143
144 self.metrics.memory_usage_bytes = self.active_perceptions.len()
146 * std::mem::size_of::<PerceptionId>()
147 + self.locked_perceptions.len() * std::mem::size_of::<PerceptionId>()
148 + self.detected_paradoxes.len() * std::mem::size_of::<uuid::Uuid>();
149 }
150}
151
152pub struct CoordinationPool {
154 active_sessions: AHashMap<uuid::Uuid, CoordinationSession>,
155 global_perception_locks: AHashMap<PerceptionId, uuid::Uuid>,
156 max_concurrent_sessions: usize,
157}
158
159impl CoordinationPool {
160 pub fn new(max_concurrent_sessions: usize) -> Self {
162 Self {
163 active_sessions: AHashMap::new(),
164 global_perception_locks: AHashMap::new(),
165 max_concurrent_sessions,
166 }
167 }
168
169 pub fn start_session(&mut self, config: CoordinationConfig) -> Result<uuid::Uuid> {
171 if self.active_sessions.len() >= self.max_concurrent_sessions {
172 return Err(CasialError::CoordinationFailure(
173 "Maximum concurrent sessions reached".to_string(),
174 )
175 .into());
176 }
177
178 let session = CoordinationSession::new(config);
179 let session_id = session.id;
180
181 self.active_sessions.insert(session_id, session);
182
183 Ok(session_id)
184 }
185
186 pub fn end_session(&mut self, session_id: uuid::Uuid) -> Result<CoordinationMetrics> {
188 if let Some(mut session) = self.active_sessions.remove(&session_id) {
189 for perception_id in &session.locked_perceptions {
191 self.global_perception_locks.remove(perception_id);
192 }
193
194 session.finalize();
195 Ok(session.metrics)
196 } else {
197 Err(
198 CasialError::CoordinationFailure(format!("Session {} not found", session_id))
199 .into(),
200 )
201 }
202 }
203
204 pub fn get_statistics(&self) -> CoordinationPoolStats {
206 let active_session_count = self.active_sessions.len();
207 let total_locked_perceptions = self.global_perception_locks.len();
208
209 let avg_session_time = if active_session_count > 0 {
210 self.active_sessions
211 .values()
212 .map(|s| s.start_time.elapsed().as_secs_f64() * 1000.0)
213 .sum::<f64>()
214 / active_session_count as f64
215 } else {
216 0.0
217 };
218
219 CoordinationPoolStats {
220 active_sessions: active_session_count,
221 max_sessions: self.max_concurrent_sessions,
222 locked_perceptions: total_locked_perceptions,
223 average_session_duration_ms: avg_session_time,
224 }
225 }
226
227 pub fn cleanup_timed_out_sessions(&mut self) -> usize {
229 let timed_out_sessions: Vec<uuid::Uuid> = self
230 .active_sessions
231 .iter()
232 .filter(|(_, session)| session.is_timed_out())
233 .map(|(id, _)| *id)
234 .collect();
235
236 let count = timed_out_sessions.len();
237
238 for session_id in timed_out_sessions {
239 let _ = self.end_session(session_id);
240 }
241
242 count
243 }
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct CoordinationPoolStats {
249 pub active_sessions: usize,
250 pub max_sessions: usize,
251 pub locked_perceptions: usize,
252 pub average_session_duration_ms: f64,
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258
259 #[test]
260 fn test_coordination_session_creation() {
261 let config = CoordinationConfig::default();
262 let session = CoordinationSession::new(config);
263 assert_eq!(session.active_perceptions.len(), 0);
264 assert_eq!(session.locked_perceptions.len(), 0);
265 }
266
267 #[test]
268 fn test_coordination_pool() {
269 let mut pool = CoordinationPool::new(10);
270 let config = CoordinationConfig::default();
271
272 let session_id = pool.start_session(config).unwrap();
273 assert_eq!(pool.active_sessions.len(), 1);
274
275 let metrics = pool.end_session(session_id).unwrap();
276 assert_eq!(pool.active_sessions.len(), 0);
277 assert!(metrics.total_coordination_time_ms >= 0.0);
278 }
279}