1use std::{collections::HashMap, sync::Arc};
7
8use anyhow::Result;
9use serde::{Deserialize, Serialize};
10use tokio::sync::RwLock;
11
12use crate::dev_log;
13
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub enum LifecycleEvent {
17 Initialize,
19 Start,
21 Stop,
23 Dispose,
25 Reload,
27 Suspend,
29 Resume,
31 Custom(String),
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
37pub enum LifecycleState {
38 Created,
40 Initializing,
42 Running,
44 Suspending,
46 Suspended,
48 Stopping,
50 Stopped,
52 Disposing,
54 Disposed,
56 Error,
58}
59
60#[allow(dead_code)]
62type LifecycleEventHandler = fn(&str, LifecycleEvent) -> Result<()>;
63
64pub struct LifecycleManager {
66 handlers:Arc<RwLock<HashMap<String, LifecycleHandlerInfo>>>,
68 states:Arc<RwLock<HashMap<String, LifecycleState>>>,
70 event_history:Arc<RwLock<Vec<LifecycleEventRecord>>>,
72}
73
74#[derive(Debug, Clone)]
76struct LifecycleHandlerInfo {
77 #[allow(dead_code)]
79 extension_id:String,
80 state:LifecycleState,
82 #[allow(dead_code)]
84 supported_events:Vec<LifecycleEvent>,
85 last_state_change:Option<u64>,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct LifecycleEventRecord {
92 pub extension_id:String,
94 pub event:LifecycleEvent,
96 pub previous_state:LifecycleState,
98 pub new_state:LifecycleState,
100 pub timestamp:u64,
102 pub duration_ms:u64,
104 pub success:bool,
106 pub error:Option<String>,
108}
109
110impl LifecycleManager {
111 pub fn new() -> Self {
113 Self {
114 handlers:Arc::new(RwLock::new(HashMap::new())),
115 states:Arc::new(RwLock::new(HashMap::new())),
116 event_history:Arc::new(RwLock::new(Vec::new())),
117 }
118 }
119
120 pub async fn register_extension(&self, extension_id:&str, initial_state:LifecycleState) -> Result<()> {
123 dev_log!("extensions", "Registering extension for lifecycle management: {}", extension_id);
124
125 let mut handlers = self.handlers.write().await;
126 handlers.insert(
127 extension_id.to_string(),
128 LifecycleHandlerInfo {
129 extension_id:extension_id.to_string(),
130 state:initial_state,
131 supported_events:vec![
132 LifecycleEvent::Initialize,
133 LifecycleEvent::Start,
134 LifecycleEvent::Stop,
135 LifecycleEvent::Dispose,
136 ],
137 last_state_change:Some(
138 std::time::SystemTime::now()
139 .duration_since(std::time::UNIX_EPOCH)
140 .map(|d| d.as_secs())
141 .unwrap_or(0),
142 ),
143 },
144 );
145
146 let mut states = self.states.write().await;
147 states.insert(extension_id.to_string(), initial_state);
148
149 dev_log!("extensions", "Extension registered: {}", extension_id);
150
151 Ok(())
152 }
153
154 pub async fn unregister_extension(&self, extension_id:&str) -> Result<()> {
157 dev_log!(
158 "extensions",
159 "Unregistering extension from lifecycle management: {}",
160 extension_id
161 );
162
163 let mut handlers = self.handlers.write().await;
164 handlers.remove(extension_id);
165
166 let mut states = self.states.write().await;
167 states.remove(extension_id);
168
169 dev_log!("extensions", "Extension unregistered: {}", extension_id);
170
171 Ok(())
172 }
173
174 pub async fn get_state(&self, extension_id:&str) -> Option<LifecycleState> {
176 self.states.read().await.get(extension_id).copied()
177 }
178
179 pub async fn transition(&self, extension_id:&str, event:LifecycleEvent) -> Result<LifecycleState> {
182 dev_log!("lifecycle", "Transitioning extension {} with event: {:?}", extension_id, event);
183
184 let start = std::time::Instant::now();
185
186 let current_state = self
188 .get_state(extension_id)
189 .await
190 .ok_or_else(|| anyhow::anyhow!("Extension not found: {}", extension_id))?;
191
192 let event_clone = event.clone();
194
195 let new_state = self.determine_next_state(current_state, event)?;
197
198 self.perform_state_transition(extension_id, event_clone.clone(), new_state)
200 .await?;
201
202 let elapsed_ms = start.elapsed().as_millis() as u64;
203
204 let record = LifecycleEventRecord {
206 extension_id:extension_id.to_string(),
207 event:event_clone,
208 previous_state:current_state,
209 new_state,
210 timestamp:std::time::SystemTime::now()
211 .duration_since(std::time::UNIX_EPOCH)
212 .map(|d| d.as_secs())
213 .unwrap_or(0),
214 duration_ms:elapsed_ms,
215 success:true,
216 error:None,
217 };
218
219 self.event_history.write().await.push(record);
220
221 dev_log!(
222 "lifecycle",
223 "Extension {} transitioned from {:?} to {:?} in {}ms",
224 extension_id,
225 current_state,
226 new_state,
227 elapsed_ms
228 );
229
230 Ok(new_state)
231 }
232
233 fn determine_next_state(&self, current_state:LifecycleState, event:LifecycleEvent) -> Result<LifecycleState> {
235 match (current_state, event.clone()) {
236 (LifecycleState::Created, LifecycleEvent::Initialize) => Ok(LifecycleState::Initializing),
237 (LifecycleState::Initializing, LifecycleEvent::Start) => Ok(LifecycleState::Running),
238 (LifecycleState::Running, LifecycleEvent::Suspend) => Ok(LifecycleState::Suspending),
239 (LifecycleState::Suspending, _) => Ok(LifecycleState::Suspended),
240 (LifecycleState::Suspended, LifecycleEvent::Resume) => Ok(LifecycleState::Running),
241 (LifecycleState::Running, LifecycleEvent::Stop) => Ok(LifecycleState::Stopping),
242 (LifecycleState::Stopping, _) => Ok(LifecycleState::Stopped),
243 (LifecycleState::Stopped | LifecycleState::Suspended, LifecycleEvent::Dispose) => {
244 Ok(LifecycleState::Disposing)
245 },
246 (LifecycleState::Disposing, _) => Ok(LifecycleState::Disposed),
247 (LifecycleState::Running, LifecycleEvent::Reload) => Ok(LifecycleState::Running),
248 _ => {
249 Err(anyhow::anyhow!(
250 "Invalid transition from {:?} with event {:?}",
251 current_state,
252 event
253 ))
254 },
255 }
256 }
257
258 async fn perform_state_transition(
260 &self,
261 extension_id:&str,
262 event:LifecycleEvent,
263 new_state:LifecycleState,
264 ) -> Result<()> {
265 dev_log!(
271 "lifecycle",
272 "Performing state transition for extension {}: {:?} -> {:?}",
273 extension_id,
274 event,
275 new_state
276 );
277
278 let mut handlers = self.handlers.write().await;
280 if let Some(handler) = handlers.get_mut(extension_id) {
281 handler.state = new_state;
282 handler.last_state_change = Some(
283 std::time::SystemTime::now()
284 .duration_since(std::time::UNIX_EPOCH)
285 .map(|d| d.as_secs())
286 .unwrap_or(0),
287 );
288 }
289
290 let mut states = self.states.write().await;
291 states.insert(extension_id.to_string(), new_state);
292
293 Ok(())
294 }
295
296 pub async fn trigger_event(&self, extension_id:&str, event:LifecycleEvent) -> Result<()> {
299 dev_log!("lifecycle", "Triggering lifecycle event for {}: {:?}", extension_id, event);
300
301 self.transition(extension_id, event).await?;
302
303 Ok(())
304 }
305
306 pub async fn get_event_history(&self) -> Vec<LifecycleEventRecord> { self.event_history.read().await.clone() }
308
309 pub async fn get_event_history_for_extension(&self, extension_id:&str) -> Vec<LifecycleEventRecord> {
311 self.event_history
312 .read()
313 .await
314 .iter()
315 .filter(|r| r.extension_id == extension_id)
316 .cloned()
317 .collect()
318 }
319
320 pub async fn get_registered_extensions(&self) -> Vec<String> {
322 self.handlers.read().await.keys().cloned().collect()
323 }
324
325 pub async fn get_extensions_in_state(&self, state:LifecycleState) -> Vec<String> {
327 self.states
328 .read()
329 .await
330 .iter()
331 .filter(|(_, s)| *s == &state)
332 .map(|(id, _)| id.clone())
333 .collect()
334 }
335}
336
337impl Default for LifecycleManager {
338 fn default() -> Self { Self::new() }
339}
340
341#[cfg(test)]
342mod tests {
343 use super::*;
344
345 #[test]
346 fn test_lifecycle_state() {
347 assert_eq!(LifecycleState::Created, LifecycleState::Created);
348 assert_eq!(LifecycleState::Running, LifecycleState::Running);
349 assert_ne!(LifecycleState::Created, LifecycleState::Running);
350 }
351
352 #[test]
353 fn test_lifecycle_event() {
354 assert_eq!(LifecycleEvent::Initialize, LifecycleEvent::Initialize);
355 assert_eq!(
356 LifecycleEvent::Custom("test".to_string()),
357 LifecycleEvent::Custom("test".to_string())
358 );
359 }
360
361 #[tokio::test]
362 async fn test_lifecycle_manager_registration() {
363 let manager = LifecycleManager::new();
364 let result = manager.register_extension("test.ext", LifecycleState::Created).await;
365
366 assert!(result.is_ok());
367 assert_eq!(manager.get_state("test.ext").await, Some(LifecycleState::Created));
368 }
369
370 #[tokio::test]
371 async fn test_state_transitions() {
372 let manager = LifecycleManager::new();
373 manager.register_extension("test.ext", LifecycleState::Created).await.unwrap();
374
375 let state = manager.transition("test.ext", LifecycleEvent::Initialize).await.unwrap();
377 assert_eq!(state, LifecycleState::Initializing);
378
379 let state = manager.transition("test.ext", LifecycleEvent::Start).await.unwrap();
381 assert_eq!(state, LifecycleState::Running);
382
383 let state = manager.transition("test.ext", LifecycleEvent::Stop).await.unwrap();
385 assert_eq!(state, LifecycleState::Stopping);
386 }
387}