1use std::{collections::HashMap, sync::Arc};
7
8use anyhow::{Context, Result};
9use serde::{Deserialize, Serialize};
10use tokio::sync::RwLock;
11use tracing::{debug, info, instrument, warn};
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
59type LifecycleEventHandler = fn(&str, LifecycleEvent) -> Result<()>;
61
62pub struct LifecycleManager {
64 handlers:Arc<RwLock<HashMap<String, LifecycleHandlerInfo>>>,
66 states:Arc<RwLock<HashMap<String, LifecycleState>>>,
68 event_history:Arc<RwLock<Vec<LifecycleEventRecord>>>,
70}
71
72#[derive(Debug, Clone)]
74struct LifecycleHandlerInfo {
75 extension_id:String,
77 state:LifecycleState,
79 supported_events:Vec<LifecycleEvent>,
81 last_state_change:Option<u64>,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct LifecycleEventRecord {
88 pub extension_id:String,
90 pub event:LifecycleEvent,
92 pub previous_state:LifecycleState,
94 pub new_state:LifecycleState,
96 pub timestamp:u64,
98 pub duration_ms:u64,
100 pub success:bool,
102 pub error:Option<String>,
104}
105
106impl LifecycleManager {
107 pub fn new() -> Self {
109 Self {
110 handlers:Arc::new(RwLock::new(HashMap::new())),
111 states:Arc::new(RwLock::new(HashMap::new())),
112 event_history:Arc::new(RwLock::new(Vec::new())),
113 }
114 }
115
116 #[instrument(skip(self, extension_id))]
118 pub async fn register_extension(&self, extension_id:&str, initial_state:LifecycleState) -> Result<()> {
119 info!("Registering extension for lifecycle management: {}", extension_id);
120
121 let mut handlers = self.handlers.write().await;
122 handlers.insert(
123 extension_id.to_string(),
124 LifecycleHandlerInfo {
125 extension_id:extension_id.to_string(),
126 state:initial_state,
127 supported_events:vec![
128 LifecycleEvent::Initialize,
129 LifecycleEvent::Start,
130 LifecycleEvent::Stop,
131 LifecycleEvent::Dispose,
132 ],
133 last_state_change:Some(
134 std::time::SystemTime::now()
135 .duration_since(std::time::UNIX_EPOCH)
136 .map(|d| d.as_secs())
137 .unwrap_or(0),
138 ),
139 },
140 );
141
142 let mut states = self.states.write().await;
143 states.insert(extension_id.to_string(), initial_state);
144
145 debug!("Extension registered: {}", extension_id);
146
147 Ok(())
148 }
149
150 #[instrument(skip(self, extension_id))]
152 pub async fn unregister_extension(&self, extension_id:&str) -> Result<()> {
153 info!("Unregistering extension from lifecycle management: {}", extension_id);
154
155 let mut handlers = self.handlers.write().await;
156 handlers.remove(extension_id);
157
158 let mut states = self.states.write().await;
159 states.remove(extension_id);
160
161 debug!("Extension unregistered: {}", extension_id);
162
163 Ok(())
164 }
165
166 pub async fn get_state(&self, extension_id:&str) -> Option<LifecycleState> {
168 self.states.read().await.get(extension_id).copied()
169 }
170
171 #[instrument(skip(self, extension_id, event))]
173 pub async fn transition(&self, extension_id:&str, event:LifecycleEvent) -> Result<LifecycleState> {
174 info!("Transitioning extension {} with event: {:?}", extension_id, event);
175
176 let start = std::time::Instant::now();
177
178 let current_state = self
180 .get_state(extension_id)
181 .await
182 .ok_or_else(|| anyhow::anyhow!("Extension not found: {}", extension_id))?;
183
184 let event_clone = event.clone();
186
187 let new_state = self.determine_next_state(current_state, event)?;
189
190 self.perform_state_transition(extension_id, event_clone.clone(), new_state).await?;
192
193 let elapsed_ms = start.elapsed().as_millis() as u64;
194
195 let record = LifecycleEventRecord {
197 extension_id:extension_id.to_string(),
198 event:event_clone,
199 previous_state:current_state,
200 new_state,
201 timestamp:std::time::SystemTime::now()
202 .duration_since(std::time::UNIX_EPOCH)
203 .map(|d| d.as_secs())
204 .unwrap_or(0),
205 duration_ms:elapsed_ms,
206 success:true,
207 error:None,
208 };
209
210 self.event_history.write().await.push(record);
211
212 debug!(
213 "Extension {} transitioned from {:?} to {:?} in {}ms",
214 extension_id, current_state, new_state, elapsed_ms
215 );
216
217 Ok(new_state)
218 }
219
220 fn determine_next_state(&self, current_state:LifecycleState, event:LifecycleEvent) -> Result<LifecycleState> {
222 match (current_state, event.clone()) {
223 (LifecycleState::Created, LifecycleEvent::Initialize) => Ok(LifecycleState::Initializing),
224 (LifecycleState::Initializing, LifecycleEvent::Start) => Ok(LifecycleState::Running),
225 (LifecycleState::Running, LifecycleEvent::Suspend) => Ok(LifecycleState::Suspending),
226 (LifecycleState::Suspending, _) => Ok(LifecycleState::Suspended),
227 (LifecycleState::Suspended, LifecycleEvent::Resume) => Ok(LifecycleState::Running),
228 (LifecycleState::Running, LifecycleEvent::Stop) => Ok(LifecycleState::Stopping),
229 (LifecycleState::Stopping, _) => Ok(LifecycleState::Stopped),
230 (LifecycleState::Stopped | LifecycleState::Suspended, LifecycleEvent::Dispose) => {
231 Ok(LifecycleState::Disposing)
232 },
233 (LifecycleState::Disposing, _) => Ok(LifecycleState::Disposed),
234 (LifecycleState::Running, LifecycleEvent::Reload) => Ok(LifecycleState::Running),
235 _ => {
236 Err(anyhow::anyhow!(
237 "Invalid transition from {:?} with event {:?}",
238 current_state,
239 event
240 ))
241 },
242 }
243 }
244
245 async fn perform_state_transition(
247 &self,
248 extension_id:&str,
249 event:LifecycleEvent,
250 new_state:LifecycleState,
251 ) -> Result<()> {
252 debug!(
258 "Performing state transition for extension {}: {:?} -> {:?}",
259 extension_id, event, new_state
260 );
261
262 let mut handlers = self.handlers.write().await;
264 if let Some(handler) = handlers.get_mut(extension_id) {
265 handler.state = new_state;
266 handler.last_state_change = Some(
267 std::time::SystemTime::now()
268 .duration_since(std::time::UNIX_EPOCH)
269 .map(|d| d.as_secs())
270 .unwrap_or(0),
271 );
272 }
273
274 let mut states = self.states.write().await;
275 states.insert(extension_id.to_string(), new_state);
276
277 Ok(())
278 }
279
280 #[instrument(skip(self, extension_id, event))]
282 pub async fn trigger_event(&self, extension_id:&str, event:LifecycleEvent) -> Result<()> {
283 info!("Triggering lifecycle event for {}: {:?}", extension_id, event);
284
285 self.transition(extension_id, event).await?;
286
287 Ok(())
288 }
289
290 pub async fn get_event_history(&self) -> Vec<LifecycleEventRecord> { self.event_history.read().await.clone() }
292
293 pub async fn get_event_history_for_extension(&self, extension_id:&str) -> Vec<LifecycleEventRecord> {
295 self.event_history
296 .read()
297 .await
298 .iter()
299 .filter(|r| r.extension_id == extension_id)
300 .cloned()
301 .collect()
302 }
303
304 pub async fn get_registered_extensions(&self) -> Vec<String> {
306 self.handlers.read().await.keys().cloned().collect()
307 }
308
309 pub async fn get_extensions_in_state(&self, state:LifecycleState) -> Vec<String> {
311 self.states
312 .read()
313 .await
314 .iter()
315 .filter(|(_, s)| *s == &state)
316 .map(|(id, _)| id.clone())
317 .collect()
318 }
319}
320
321impl Default for LifecycleManager {
322 fn default() -> Self { Self::new() }
323}
324
325#[cfg(test)]
326mod tests {
327 use super::*;
328
329 #[test]
330 fn test_lifecycle_state() {
331 assert_eq!(LifecycleState::Created, LifecycleState::Created);
332 assert_eq!(LifecycleState::Running, LifecycleState::Running);
333 assert_ne!(LifecycleState::Created, LifecycleState::Running);
334 }
335
336 #[test]
337 fn test_lifecycle_event() {
338 assert_eq!(LifecycleEvent::Initialize, LifecycleEvent::Initialize);
339 assert_eq!(
340 LifecycleEvent::Custom("test".to_string()),
341 LifecycleEvent::Custom("test".to_string())
342 );
343 }
344
345 #[tokio::test]
346 async fn test_lifecycle_manager_registration() {
347 let manager = LifecycleManager::new();
348 let result = manager.register_extension("test.ext", LifecycleState::Created).await;
349
350 assert!(result.is_ok());
351 assert_eq!(manager.get_state("test.ext").await, Some(LifecycleState::Created));
352 }
353
354 #[tokio::test]
355 async fn test_state_transitions() {
356 let manager = LifecycleManager::new();
357 manager.register_extension("test.ext", LifecycleState::Created).await.unwrap();
358
359 let state = manager.transition("test.ext", LifecycleEvent::Initialize).await.unwrap();
361 assert_eq!(state, LifecycleState::Initializing);
362
363 let state = manager.transition("test.ext", LifecycleEvent::Start).await.unwrap();
365 assert_eq!(state, LifecycleState::Running);
366
367 let state = manager.transition("test.ext", LifecycleEvent::Stop).await.unwrap();
369 assert_eq!(state, LifecycleState::Stopping);
370 }
371}