Skip to main content

Grove/Host/
Lifecycle.rs

1//! Lifecycle Management Module
2//!
3//! Handles extension lifecycle events such as initialization,
4//! shutdown, and state transitions.
5
6use std::{collections::HashMap, sync::Arc};
7
8use anyhow::Result;
9use serde::{Deserialize, Serialize};
10use tokio::sync::RwLock;
11use crate::dev_log;
12
13/// Lifecycle event types
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15pub enum LifecycleEvent {
16	/// Extension is being initialized
17	Initialize,
18	/// Extension is being started
19	Start,
20	/// Extension is being stopped
21	Stop,
22	/// Extension is being disposed
23	Dispose,
24	/// Extension is reloading (hot reload)
25	Reload,
26	/// Extension is being suspended
27	Suspend,
28	/// Extension is being resumed
29	Resume,
30	/// Custom lifecycle event
31	Custom(String),
32}
33
34/// Lifecycle state for extensions
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36pub enum LifecycleState {
37	/// Extension has been created but not initialized
38	Created,
39	/// Extension is being initialized
40	Initializing,
41	/// Extension is active and running
42	Running,
43	/// Extension is being suspended
44	Suspending,
45	/// Extension is suspended
46	Suspended,
47	/// Extension is being stopped
48	Stopping,
49	/// Extension has been stopped
50	Stopped,
51	/// Extension is being disposed
52	Disposing,
53	/// Extension has been disposed
54	Disposed,
55	/// Extension is in an error state
56	Error,
57}
58
59/// Lifecycle event handler callback
60#[allow(dead_code)]
61type LifecycleEventHandler = fn(&str, LifecycleEvent) -> Result<()>;
62
63/// Lifecycle manager for extension lifecycle
64pub struct LifecycleManager {
65	/// Event handlers
66	handlers:Arc<RwLock<HashMap<String, LifecycleHandlerInfo>>>,
67	/// Extension states
68	states:Arc<RwLock<HashMap<String, LifecycleState>>>,
69	/// Event history
70	event_history:Arc<RwLock<Vec<LifecycleEventRecord>>>,
71}
72
73/// Information about a lifecycle handler
74#[derive(Debug, Clone)]
75struct LifecycleHandlerInfo {
76	/// Extension ID
77	#[allow(dead_code)]
78	extension_id:String,
79	/// Current state
80	state:LifecycleState,
81	/// Supported events
82	#[allow(dead_code)]
83	supported_events:Vec<LifecycleEvent>,
84	/// Last state change timestamp
85	last_state_change:Option<u64>,
86}
87
88/// Record of a lifecycle event
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct LifecycleEventRecord {
91	/// Extension ID
92	pub extension_id:String,
93	/// Event that occurred
94	pub event:LifecycleEvent,
95	/// Previous state
96	pub previous_state:LifecycleState,
97	/// New state
98	pub new_state:LifecycleState,
99	/// Timestamp
100	pub timestamp:u64,
101	/// Duration in milliseconds
102	pub duration_ms:u64,
103	/// Success flag
104	pub success:bool,
105	/// Error message (if failed)
106	pub error:Option<String>,
107}
108
109impl LifecycleManager {
110	/// Create a new lifecycle manager
111	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	/// Register an extension for lifecycle management
120	
121	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	/// Unregister an extension from lifecycle management
154	
155	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	/// Get the current state of an extension
170	pub async fn get_state(&self, extension_id:&str) -> Option<LifecycleState> {
171		self.states.read().await.get(extension_id).copied()
172	}
173
174	/// Transition an extension to a new state
175	
176	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		// Get current state
182		let current_state = self
183			.get_state(extension_id)
184			.await
185			.ok_or_else(|| anyhow::anyhow!("Extension not found: {}", extension_id))?;
186
187		// Clone event for later use before moving it
188		let event_clone = event.clone();
189
190		// Determine new state based on event
191		let new_state = self.determine_next_state(current_state, event)?;
192
193		// Perform state transition (in real implementation, this would call extension)
194		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		// Record event
200		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	/// Determine the next state based on current state and event
226	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	/// Perform actual state transition
251	async fn perform_state_transition(
252		&self,
253		extension_id:&str,
254		event:LifecycleEvent,
255		new_state:LifecycleState,
256	) -> Result<()> {
257		// In real implementation, this would:
258		// 1. Call the extension's lifecycle handler
259		// 2. Handle any errors
260		// 3. Rollback on failure
261
262		dev_log!(
263			"lifecycle",
264			"Performing state transition for extension {}: {:?} -> {:?}",
265			extension_id, event, new_state
266		);
267
268		// Update state
269		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	/// Trigger a lifecycle event for an extension
287	
288	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	/// Get event history
297	pub async fn get_event_history(&self) -> Vec<LifecycleEventRecord> { self.event_history.read().await.clone() }
298
299	/// Get event history for a specific extension
300	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	/// Get all registered extensions
311	pub async fn get_registered_extensions(&self) -> Vec<String> {
312		self.handlers.read().await.keys().cloned().collect()
313	}
314
315	/// Get extensions in a specific state
316	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		// Initialize
366		let state = manager.transition("test.ext", LifecycleEvent::Initialize).await.unwrap();
367		assert_eq!(state, LifecycleState::Initializing);
368
369		// Start
370		let state = manager.transition("test.ext", LifecycleEvent::Start).await.unwrap();
371		assert_eq!(state, LifecycleState::Running);
372
373		// Stop
374		let state = manager.transition("test.ext", LifecycleEvent::Stop).await.unwrap();
375		assert_eq!(state, LifecycleState::Stopping);
376	}
377}