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 tracing::{debug, info, instrument};
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	#[instrument(skip(self, extension_id))]
121	pub async fn register_extension(&self, extension_id:&str, initial_state:LifecycleState) -> Result<()> {
122		info!("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		debug!("Extension registered: {}", extension_id);
149
150		Ok(())
151	}
152
153	/// Unregister an extension from lifecycle management
154	#[instrument(skip(self, extension_id))]
155	pub async fn unregister_extension(&self, extension_id:&str) -> Result<()> {
156		info!("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		debug!("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	#[instrument(skip(self, extension_id, event))]
176	pub async fn transition(&self, extension_id:&str, event:LifecycleEvent) -> Result<LifecycleState> {
177		info!("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		debug!(
217			"Extension {} transitioned from {:?} to {:?} in {}ms",
218			extension_id, current_state, new_state, elapsed_ms
219		);
220
221		Ok(new_state)
222	}
223
224	/// Determine the next state based on current state and event
225	fn determine_next_state(&self, current_state:LifecycleState, event:LifecycleEvent) -> Result<LifecycleState> {
226		match (current_state, event.clone()) {
227			(LifecycleState::Created, LifecycleEvent::Initialize) => Ok(LifecycleState::Initializing),
228			(LifecycleState::Initializing, LifecycleEvent::Start) => Ok(LifecycleState::Running),
229			(LifecycleState::Running, LifecycleEvent::Suspend) => Ok(LifecycleState::Suspending),
230			(LifecycleState::Suspending, _) => Ok(LifecycleState::Suspended),
231			(LifecycleState::Suspended, LifecycleEvent::Resume) => Ok(LifecycleState::Running),
232			(LifecycleState::Running, LifecycleEvent::Stop) => Ok(LifecycleState::Stopping),
233			(LifecycleState::Stopping, _) => Ok(LifecycleState::Stopped),
234			(LifecycleState::Stopped | LifecycleState::Suspended, LifecycleEvent::Dispose) => {
235				Ok(LifecycleState::Disposing)
236			},
237			(LifecycleState::Disposing, _) => Ok(LifecycleState::Disposed),
238			(LifecycleState::Running, LifecycleEvent::Reload) => Ok(LifecycleState::Running),
239			_ => {
240				Err(anyhow::anyhow!(
241					"Invalid transition from {:?} with event {:?}",
242					current_state,
243					event
244				))
245			},
246		}
247	}
248
249	/// Perform actual state transition
250	async fn perform_state_transition(
251		&self,
252		extension_id:&str,
253		event:LifecycleEvent,
254		new_state:LifecycleState,
255	) -> Result<()> {
256		// In real implementation, this would:
257		// 1. Call the extension's lifecycle handler
258		// 2. Handle any errors
259		// 3. Rollback on failure
260
261		debug!(
262			"Performing state transition for extension {}: {:?} -> {:?}",
263			extension_id, event, new_state
264		);
265
266		// Update state
267		let mut handlers = self.handlers.write().await;
268		if let Some(handler) = handlers.get_mut(extension_id) {
269			handler.state = new_state;
270			handler.last_state_change = Some(
271				std::time::SystemTime::now()
272					.duration_since(std::time::UNIX_EPOCH)
273					.map(|d| d.as_secs())
274					.unwrap_or(0),
275			);
276		}
277
278		let mut states = self.states.write().await;
279		states.insert(extension_id.to_string(), new_state);
280
281		Ok(())
282	}
283
284	/// Trigger a lifecycle event for an extension
285	#[instrument(skip(self, extension_id, event))]
286	pub async fn trigger_event(&self, extension_id:&str, event:LifecycleEvent) -> Result<()> {
287		info!("Triggering lifecycle event for {}: {:?}", extension_id, event);
288
289		self.transition(extension_id, event).await?;
290
291		Ok(())
292	}
293
294	/// Get event history
295	pub async fn get_event_history(&self) -> Vec<LifecycleEventRecord> { self.event_history.read().await.clone() }
296
297	/// Get event history for a specific extension
298	pub async fn get_event_history_for_extension(&self, extension_id:&str) -> Vec<LifecycleEventRecord> {
299		self.event_history
300			.read()
301			.await
302			.iter()
303			.filter(|r| r.extension_id == extension_id)
304			.cloned()
305			.collect()
306	}
307
308	/// Get all registered extensions
309	pub async fn get_registered_extensions(&self) -> Vec<String> {
310		self.handlers.read().await.keys().cloned().collect()
311	}
312
313	/// Get extensions in a specific state
314	pub async fn get_extensions_in_state(&self, state:LifecycleState) -> Vec<String> {
315		self.states
316			.read()
317			.await
318			.iter()
319			.filter(|(_, s)| *s == &state)
320			.map(|(id, _)| id.clone())
321			.collect()
322	}
323}
324
325impl Default for LifecycleManager {
326	fn default() -> Self { Self::new() }
327}
328
329#[cfg(test)]
330mod tests {
331	use super::*;
332
333	#[test]
334	fn test_lifecycle_state() {
335		assert_eq!(LifecycleState::Created, LifecycleState::Created);
336		assert_eq!(LifecycleState::Running, LifecycleState::Running);
337		assert_ne!(LifecycleState::Created, LifecycleState::Running);
338	}
339
340	#[test]
341	fn test_lifecycle_event() {
342		assert_eq!(LifecycleEvent::Initialize, LifecycleEvent::Initialize);
343		assert_eq!(
344			LifecycleEvent::Custom("test".to_string()),
345			LifecycleEvent::Custom("test".to_string())
346		);
347	}
348
349	#[tokio::test]
350	async fn test_lifecycle_manager_registration() {
351		let manager = LifecycleManager::new();
352		let result = manager.register_extension("test.ext", LifecycleState::Created).await;
353
354		assert!(result.is_ok());
355		assert_eq!(manager.get_state("test.ext").await, Some(LifecycleState::Created));
356	}
357
358	#[tokio::test]
359	async fn test_state_transitions() {
360		let manager = LifecycleManager::new();
361		manager.register_extension("test.ext", LifecycleState::Created).await.unwrap();
362
363		// Initialize
364		let state = manager.transition("test.ext", LifecycleEvent::Initialize).await.unwrap();
365		assert_eq!(state, LifecycleState::Initializing);
366
367		// Start
368		let state = manager.transition("test.ext", LifecycleEvent::Start).await.unwrap();
369		assert_eq!(state, LifecycleState::Running);
370
371		// Stop
372		let state = manager.transition("test.ext", LifecycleEvent::Stop).await.unwrap();
373		assert_eq!(state, LifecycleState::Stopping);
374	}
375}