1use std::{collections::HashMap, sync::Arc};
7
8use anyhow::Result;
9use serde::{Deserialize, Serialize};
10use tokio::sync::RwLock;
11use crate::dev_log;
12
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15pub enum LifecycleEvent {
16 Initialize,
18 Start,
20 Stop,
22 Dispose,
24 Reload,
26 Suspend,
28 Resume,
30 Custom(String),
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36pub enum LifecycleState {
37 Created,
39 Initializing,
41 Running,
43 Suspending,
45 Suspended,
47 Stopping,
49 Stopped,
51 Disposing,
53 Disposed,
55 Error,
57}
58
59#[allow(dead_code)]
61type LifecycleEventHandler = fn(&str, LifecycleEvent) -> Result<()>;
62
63pub struct LifecycleManager {
65 handlers:Arc<RwLock<HashMap<String, LifecycleHandlerInfo>>>,
67 states:Arc<RwLock<HashMap<String, LifecycleState>>>,
69 event_history:Arc<RwLock<Vec<LifecycleEventRecord>>>,
71}
72
73#[derive(Debug, Clone)]
75struct LifecycleHandlerInfo {
76 #[allow(dead_code)]
78 extension_id:String,
79 state:LifecycleState,
81 #[allow(dead_code)]
83 supported_events:Vec<LifecycleEvent>,
84 last_state_change:Option<u64>,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct LifecycleEventRecord {
91 pub extension_id:String,
93 pub event:LifecycleEvent,
95 pub previous_state:LifecycleState,
97 pub new_state:LifecycleState,
99 pub timestamp:u64,
101 pub duration_ms:u64,
103 pub success:bool,
105 pub error:Option<String>,
107}
108
109impl LifecycleManager {
110 pub fn new() -> Self {
112 Self {
113 handlers:Arc::new(RwLock::new(HashMap::new())),
114 states:Arc::new(RwLock::new(HashMap::new())),
115 event_history:Arc::new(RwLock::new(Vec::new())),
116 }
117 }
118
119 pub async fn register_extension(&self, extension_id:&str, initial_state:LifecycleState) -> Result<()> {
122 dev_log!("extensions", "Registering extension for lifecycle management: {}", extension_id);
123
124 let mut handlers = self.handlers.write().await;
125 handlers.insert(
126 extension_id.to_string(),
127 LifecycleHandlerInfo {
128 extension_id:extension_id.to_string(),
129 state:initial_state,
130 supported_events:vec![
131 LifecycleEvent::Initialize,
132 LifecycleEvent::Start,
133 LifecycleEvent::Stop,
134 LifecycleEvent::Dispose,
135 ],
136 last_state_change:Some(
137 std::time::SystemTime::now()
138 .duration_since(std::time::UNIX_EPOCH)
139 .map(|d| d.as_secs())
140 .unwrap_or(0),
141 ),
142 },
143 );
144
145 let mut states = self.states.write().await;
146 states.insert(extension_id.to_string(), initial_state);
147
148 dev_log!("extensions", "Extension registered: {}", extension_id);
149
150 Ok(())
151 }
152
153 pub async fn unregister_extension(&self, extension_id:&str) -> Result<()> {
156 dev_log!("extensions", "Unregistering extension from lifecycle management: {}", extension_id);
157
158 let mut handlers = self.handlers.write().await;
159 handlers.remove(extension_id);
160
161 let mut states = self.states.write().await;
162 states.remove(extension_id);
163
164 dev_log!("extensions", "Extension unregistered: {}", extension_id);
165
166 Ok(())
167 }
168
169 pub async fn get_state(&self, extension_id:&str) -> Option<LifecycleState> {
171 self.states.read().await.get(extension_id).copied()
172 }
173
174 pub async fn transition(&self, extension_id:&str, event:LifecycleEvent) -> Result<LifecycleState> {
177 dev_log!("lifecycle", "Transitioning extension {} with event: {:?}", extension_id, event);
178
179 let start = std::time::Instant::now();
180
181 let current_state = self
183 .get_state(extension_id)
184 .await
185 .ok_or_else(|| anyhow::anyhow!("Extension not found: {}", extension_id))?;
186
187 let event_clone = event.clone();
189
190 let new_state = self.determine_next_state(current_state, event)?;
192
193 self.perform_state_transition(extension_id, event_clone.clone(), new_state)
195 .await?;
196
197 let elapsed_ms = start.elapsed().as_millis() as u64;
198
199 let record = LifecycleEventRecord {
201 extension_id:extension_id.to_string(),
202 event:event_clone,
203 previous_state:current_state,
204 new_state,
205 timestamp:std::time::SystemTime::now()
206 .duration_since(std::time::UNIX_EPOCH)
207 .map(|d| d.as_secs())
208 .unwrap_or(0),
209 duration_ms:elapsed_ms,
210 success:true,
211 error:None,
212 };
213
214 self.event_history.write().await.push(record);
215
216 dev_log!(
217 "lifecycle",
218 "Extension {} transitioned from {:?} to {:?} in {}ms",
219 extension_id, current_state, new_state, elapsed_ms
220 );
221
222 Ok(new_state)
223 }
224
225 fn determine_next_state(&self, current_state:LifecycleState, event:LifecycleEvent) -> Result<LifecycleState> {
227 match (current_state, event.clone()) {
228 (LifecycleState::Created, LifecycleEvent::Initialize) => Ok(LifecycleState::Initializing),
229 (LifecycleState::Initializing, LifecycleEvent::Start) => Ok(LifecycleState::Running),
230 (LifecycleState::Running, LifecycleEvent::Suspend) => Ok(LifecycleState::Suspending),
231 (LifecycleState::Suspending, _) => Ok(LifecycleState::Suspended),
232 (LifecycleState::Suspended, LifecycleEvent::Resume) => Ok(LifecycleState::Running),
233 (LifecycleState::Running, LifecycleEvent::Stop) => Ok(LifecycleState::Stopping),
234 (LifecycleState::Stopping, _) => Ok(LifecycleState::Stopped),
235 (LifecycleState::Stopped | LifecycleState::Suspended, LifecycleEvent::Dispose) => {
236 Ok(LifecycleState::Disposing)
237 },
238 (LifecycleState::Disposing, _) => Ok(LifecycleState::Disposed),
239 (LifecycleState::Running, LifecycleEvent::Reload) => Ok(LifecycleState::Running),
240 _ => {
241 Err(anyhow::anyhow!(
242 "Invalid transition from {:?} with event {:?}",
243 current_state,
244 event
245 ))
246 },
247 }
248 }
249
250 async fn perform_state_transition(
252 &self,
253 extension_id:&str,
254 event:LifecycleEvent,
255 new_state:LifecycleState,
256 ) -> Result<()> {
257 dev_log!(
263 "lifecycle",
264 "Performing state transition for extension {}: {:?} -> {:?}",
265 extension_id, event, new_state
266 );
267
268 let mut handlers = self.handlers.write().await;
270 if let Some(handler) = handlers.get_mut(extension_id) {
271 handler.state = new_state;
272 handler.last_state_change = Some(
273 std::time::SystemTime::now()
274 .duration_since(std::time::UNIX_EPOCH)
275 .map(|d| d.as_secs())
276 .unwrap_or(0),
277 );
278 }
279
280 let mut states = self.states.write().await;
281 states.insert(extension_id.to_string(), new_state);
282
283 Ok(())
284 }
285
286 pub async fn trigger_event(&self, extension_id:&str, event:LifecycleEvent) -> Result<()> {
289 dev_log!("lifecycle", "Triggering lifecycle event for {}: {:?}", extension_id, event);
290
291 self.transition(extension_id, event).await?;
292
293 Ok(())
294 }
295
296 pub async fn get_event_history(&self) -> Vec<LifecycleEventRecord> { self.event_history.read().await.clone() }
298
299 pub async fn get_event_history_for_extension(&self, extension_id:&str) -> Vec<LifecycleEventRecord> {
301 self.event_history
302 .read()
303 .await
304 .iter()
305 .filter(|r| r.extension_id == extension_id)
306 .cloned()
307 .collect()
308 }
309
310 pub async fn get_registered_extensions(&self) -> Vec<String> {
312 self.handlers.read().await.keys().cloned().collect()
313 }
314
315 pub async fn get_extensions_in_state(&self, state:LifecycleState) -> Vec<String> {
317 self.states
318 .read()
319 .await
320 .iter()
321 .filter(|(_, s)| *s == &state)
322 .map(|(id, _)| id.clone())
323 .collect()
324 }
325}
326
327impl Default for LifecycleManager {
328 fn default() -> Self { Self::new() }
329}
330
331#[cfg(test)]
332mod tests {
333 use super::*;
334
335 #[test]
336 fn test_lifecycle_state() {
337 assert_eq!(LifecycleState::Created, LifecycleState::Created);
338 assert_eq!(LifecycleState::Running, LifecycleState::Running);
339 assert_ne!(LifecycleState::Created, LifecycleState::Running);
340 }
341
342 #[test]
343 fn test_lifecycle_event() {
344 assert_eq!(LifecycleEvent::Initialize, LifecycleEvent::Initialize);
345 assert_eq!(
346 LifecycleEvent::Custom("test".to_string()),
347 LifecycleEvent::Custom("test".to_string())
348 );
349 }
350
351 #[tokio::test]
352 async fn test_lifecycle_manager_registration() {
353 let manager = LifecycleManager::new();
354 let result = manager.register_extension("test.ext", LifecycleState::Created).await;
355
356 assert!(result.is_ok());
357 assert_eq!(manager.get_state("test.ext").await, Some(LifecycleState::Created));
358 }
359
360 #[tokio::test]
361 async fn test_state_transitions() {
362 let manager = LifecycleManager::new();
363 manager.register_extension("test.ext", LifecycleState::Created).await.unwrap();
364
365 let state = manager.transition("test.ext", LifecycleEvent::Initialize).await.unwrap();
367 assert_eq!(state, LifecycleState::Initializing);
368
369 let state = manager.transition("test.ext", LifecycleEvent::Start).await.unwrap();
371 assert_eq!(state, LifecycleState::Running);
372
373 let state = manager.transition("test.ext", LifecycleEvent::Stop).await.unwrap();
375 assert_eq!(state, LifecycleState::Stopping);
376 }
377}