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
20 Start,
22
23 Stop,
25
26 Dispose,
28
29 Reload,
31
32 Suspend,
34
35 Resume,
37
38 Custom(String),
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
44pub enum LifecycleState {
45 Created,
47
48 Initializing,
50
51 Running,
53
54 Suspending,
56
57 Suspended,
59
60 Stopping,
62
63 Stopped,
65
66 Disposing,
68
69 Disposed,
71
72 Error,
74}
75
76#[allow(dead_code)]
78type LifecycleEventHandler = fn(&str, LifecycleEvent) -> Result<()>;
79
80pub struct LifecycleManager {
82 handlers:Arc<RwLock<HashMap<String, LifecycleHandlerInfo>>>,
84
85 states:Arc<RwLock<HashMap<String, LifecycleState>>>,
87
88 event_history:Arc<RwLock<Vec<LifecycleEventRecord>>>,
90}
91
92#[derive(Debug, Clone)]
94struct LifecycleHandlerInfo {
95 #[allow(dead_code)]
97 extension_id:String,
98
99 state:LifecycleState,
101
102 #[allow(dead_code)]
104 supported_events:Vec<LifecycleEvent>,
105
106 last_state_change:Option<u64>,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct LifecycleEventRecord {
113 pub extension_id:String,
115
116 pub event:LifecycleEvent,
118
119 pub previous_state:LifecycleState,
121
122 pub new_state:LifecycleState,
124
125 pub timestamp:u64,
127
128 pub duration_ms:u64,
130
131 pub success:bool,
133
134 pub error:Option<String>,
136}
137
138impl LifecycleManager {
139 pub fn new() -> Self {
141 Self {
142 handlers:Arc::new(RwLock::new(HashMap::new())),
143
144 states:Arc::new(RwLock::new(HashMap::new())),
145
146 event_history:Arc::new(RwLock::new(Vec::new())),
147 }
148 }
149
150 pub async fn register_extension(&self, extension_id:&str, initial_state:LifecycleState) -> Result<()> {
153 dev_log!("extensions", "Registering extension for lifecycle management: {}", extension_id);
154
155 let mut handlers = self.handlers.write().await;
156
157 handlers.insert(
158 extension_id.to_string(),
159 LifecycleHandlerInfo {
160 extension_id:extension_id.to_string(),
161 state:initial_state,
162 supported_events:vec![
163 LifecycleEvent::Initialize,
164 LifecycleEvent::Start,
165 LifecycleEvent::Stop,
166 LifecycleEvent::Dispose,
167 ],
168 last_state_change:Some(
169 std::time::SystemTime::now()
170 .duration_since(std::time::UNIX_EPOCH)
171 .map(|d| d.as_secs())
172 .unwrap_or(0),
173 ),
174 },
175 );
176
177 let mut states = self.states.write().await;
178
179 states.insert(extension_id.to_string(), initial_state);
180
181 dev_log!("extensions", "Extension registered: {}", extension_id);
182
183 Ok(())
184 }
185
186 pub async fn unregister_extension(&self, extension_id:&str) -> Result<()> {
189 dev_log!(
190 "extensions",
191 "Unregistering extension from lifecycle management: {}",
192 extension_id
193 );
194
195 let mut handlers = self.handlers.write().await;
196
197 handlers.remove(extension_id);
198
199 let mut states = self.states.write().await;
200
201 states.remove(extension_id);
202
203 dev_log!("extensions", "Extension unregistered: {}", extension_id);
204
205 Ok(())
206 }
207
208 pub async fn get_state(&self, extension_id:&str) -> Option<LifecycleState> {
210 self.states.read().await.get(extension_id).copied()
211 }
212
213 pub async fn transition(&self, extension_id:&str, event:LifecycleEvent) -> Result<LifecycleState> {
216 dev_log!("lifecycle", "Transitioning extension {} with event: {:?}", extension_id, event);
217
218 let start = std::time::Instant::now();
219
220 let current_state = self
222 .get_state(extension_id)
223 .await
224 .ok_or_else(|| anyhow::anyhow!("Extension not found: {}", extension_id))?;
225
226 let event_clone = event.clone();
228
229 let new_state = self.determine_next_state(current_state, event)?;
231
232 self.perform_state_transition(extension_id, event_clone.clone(), new_state)
234 .await?;
235
236 let elapsed_ms = start.elapsed().as_millis() as u64;
237
238 let record = LifecycleEventRecord {
240 extension_id:extension_id.to_string(),
241
242 event:event_clone,
243
244 previous_state:current_state,
245
246 new_state,
247
248 timestamp:std::time::SystemTime::now()
249 .duration_since(std::time::UNIX_EPOCH)
250 .map(|d| d.as_secs())
251 .unwrap_or(0),
252
253 duration_ms:elapsed_ms,
254
255 success:true,
256
257 error:None,
258 };
259
260 self.event_history.write().await.push(record);
261
262 dev_log!(
263 "lifecycle",
264 "Extension {} transitioned from {:?} to {:?} in {}ms",
265 extension_id,
266 current_state,
267 new_state,
268 elapsed_ms
269 );
270
271 Ok(new_state)
272 }
273
274 fn determine_next_state(&self, current_state:LifecycleState, event:LifecycleEvent) -> Result<LifecycleState> {
276 match (current_state, event.clone()) {
277 (LifecycleState::Created, LifecycleEvent::Initialize) => Ok(LifecycleState::Initializing),
278
279 (LifecycleState::Initializing, LifecycleEvent::Start) => Ok(LifecycleState::Running),
280
281 (LifecycleState::Running, LifecycleEvent::Suspend) => Ok(LifecycleState::Suspending),
282
283 (LifecycleState::Suspending, _) => Ok(LifecycleState::Suspended),
284
285 (LifecycleState::Suspended, LifecycleEvent::Resume) => Ok(LifecycleState::Running),
286
287 (LifecycleState::Running, LifecycleEvent::Stop) => Ok(LifecycleState::Stopping),
288
289 (LifecycleState::Stopping, _) => Ok(LifecycleState::Stopped),
290
291 (LifecycleState::Stopped | LifecycleState::Suspended, LifecycleEvent::Dispose) => {
292 Ok(LifecycleState::Disposing)
293 },
294
295 (LifecycleState::Disposing, _) => Ok(LifecycleState::Disposed),
296
297 (LifecycleState::Running, LifecycleEvent::Reload) => Ok(LifecycleState::Running),
298
299 _ => {
300 Err(anyhow::anyhow!(
301 "Invalid transition from {:?} with event {:?}",
302 current_state,
303 event
304 ))
305 },
306 }
307 }
308
309 async fn perform_state_transition(
311 &self,
312
313 extension_id:&str,
314
315 event:LifecycleEvent,
316
317 new_state:LifecycleState,
318 ) -> Result<()> {
319 dev_log!(
325 "lifecycle",
326 "Performing state transition for extension {}: {:?} -> {:?}",
327 extension_id,
328 event,
329 new_state
330 );
331
332 let mut handlers = self.handlers.write().await;
334
335 if let Some(handler) = handlers.get_mut(extension_id) {
336 handler.state = new_state;
337
338 handler.last_state_change = Some(
339 std::time::SystemTime::now()
340 .duration_since(std::time::UNIX_EPOCH)
341 .map(|d| d.as_secs())
342 .unwrap_or(0),
343 );
344 }
345
346 let mut states = self.states.write().await;
347
348 states.insert(extension_id.to_string(), new_state);
349
350 Ok(())
351 }
352
353 pub async fn trigger_event(&self, extension_id:&str, event:LifecycleEvent) -> Result<()> {
356 dev_log!("lifecycle", "Triggering lifecycle event for {}: {:?}", extension_id, event);
357
358 self.transition(extension_id, event).await?;
359
360 Ok(())
361 }
362
363 pub async fn get_event_history(&self) -> Vec<LifecycleEventRecord> { self.event_history.read().await.clone() }
365
366 pub async fn get_event_history_for_extension(&self, extension_id:&str) -> Vec<LifecycleEventRecord> {
368 self.event_history
369 .read()
370 .await
371 .iter()
372 .filter(|r| r.extension_id == extension_id)
373 .cloned()
374 .collect()
375 }
376
377 pub async fn get_registered_extensions(&self) -> Vec<String> {
379 self.handlers.read().await.keys().cloned().collect()
380 }
381
382 pub async fn get_extensions_in_state(&self, state:LifecycleState) -> Vec<String> {
384 self.states
385 .read()
386 .await
387 .iter()
388 .filter(|(_, s)| *s == &state)
389 .map(|(id, _)| id.clone())
390 .collect()
391 }
392}
393
394impl Default for LifecycleManager {
395 fn default() -> Self { Self::new() }
396}
397
398#[cfg(test)]
399mod tests {
400
401 use super::*;
402
403 #[test]
404 fn test_lifecycle_state() {
405 assert_eq!(LifecycleState::Created, LifecycleState::Created);
406
407 assert_eq!(LifecycleState::Running, LifecycleState::Running);
408
409 assert_ne!(LifecycleState::Created, LifecycleState::Running);
410 }
411
412 #[test]
413 fn test_lifecycle_event() {
414 assert_eq!(LifecycleEvent::Initialize, LifecycleEvent::Initialize);
415
416 assert_eq!(
417 LifecycleEvent::Custom("test".to_string()),
418 LifecycleEvent::Custom("test".to_string())
419 );
420 }
421
422 #[tokio::test]
423 async fn test_lifecycle_manager_registration() {
424 let manager = LifecycleManager::new();
425
426 let result = manager.register_extension("test.ext", LifecycleState::Created).await;
427
428 assert!(result.is_ok());
429
430 assert_eq!(manager.get_state("test.ext").await, Some(LifecycleState::Created));
431 }
432
433 #[tokio::test]
434 async fn test_state_transitions() {
435 let manager = LifecycleManager::new();
436
437 manager.register_extension("test.ext", LifecycleState::Created).await.unwrap();
438
439 let state = manager.transition("test.ext", LifecycleEvent::Initialize).await.unwrap();
441
442 assert_eq!(state, LifecycleState::Initializing);
443
444 let state = manager.transition("test.ext", LifecycleEvent::Start).await.unwrap();
446
447 assert_eq!(state, LifecycleState::Running);
448
449 let state = manager.transition("test.ext", LifecycleEvent::Stop).await.unwrap();
451
452 assert_eq!(state, LifecycleState::Stopping);
453 }
454}