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;
11
12use crate::dev_log;
13
14/// Lifecycle event types
15#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub enum LifecycleEvent {
17	/// Extension is being initialized
18	Initialize,
19	/// Extension is being started
20	Start,
21	/// Extension is being stopped
22	Stop,
23	/// Extension is being disposed
24	Dispose,
25	/// Extension is reloading (hot reload)
26	Reload,
27	/// Extension is being suspended
28	Suspend,
29	/// Extension is being resumed
30	Resume,
31	/// Custom lifecycle event
32	Custom(String),
33}
34
35/// Lifecycle state for extensions
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
37pub enum LifecycleState {
38	/// Extension has been created but not initialized
39	Created,
40	/// Extension is being initialized
41	Initializing,
42	/// Extension is active and running
43	Running,
44	/// Extension is being suspended
45	Suspending,
46	/// Extension is suspended
47	Suspended,
48	/// Extension is being stopped
49	Stopping,
50	/// Extension has been stopped
51	Stopped,
52	/// Extension is being disposed
53	Disposing,
54	/// Extension has been disposed
55	Disposed,
56	/// Extension is in an error state
57	Error,
58}
59
60/// Lifecycle event handler callback
61#[allow(dead_code)]
62type LifecycleEventHandler = fn(&str, LifecycleEvent) -> Result<()>;
63
64/// Lifecycle manager for extension lifecycle
65pub struct LifecycleManager {
66	/// Event handlers
67	handlers:Arc<RwLock<HashMap<String, LifecycleHandlerInfo>>>,
68	/// Extension states
69	states:Arc<RwLock<HashMap<String, LifecycleState>>>,
70	/// Event history
71	event_history:Arc<RwLock<Vec<LifecycleEventRecord>>>,
72}
73
74/// Information about a lifecycle handler
75#[derive(Debug, Clone)]
76struct LifecycleHandlerInfo {
77	/// Extension ID
78	#[allow(dead_code)]
79	extension_id:String,
80	/// Current state
81	state:LifecycleState,
82	/// Supported events
83	#[allow(dead_code)]
84	supported_events:Vec<LifecycleEvent>,
85	/// Last state change timestamp
86	last_state_change:Option<u64>,
87}
88
89/// Record of a lifecycle event
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct LifecycleEventRecord {
92	/// Extension ID
93	pub extension_id:String,
94	/// Event that occurred
95	pub event:LifecycleEvent,
96	/// Previous state
97	pub previous_state:LifecycleState,
98	/// New state
99	pub new_state:LifecycleState,
100	/// Timestamp
101	pub timestamp:u64,
102	/// Duration in milliseconds
103	pub duration_ms:u64,
104	/// Success flag
105	pub success:bool,
106	/// Error message (if failed)
107	pub error:Option<String>,
108}
109
110impl LifecycleManager {
111	/// Create a new lifecycle manager
112	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	/// Register an extension for lifecycle management
121
122	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	/// Unregister an extension from lifecycle management
155
156	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	/// Get the current state of an extension
175	pub async fn get_state(&self, extension_id:&str) -> Option<LifecycleState> {
176		self.states.read().await.get(extension_id).copied()
177	}
178
179	/// Transition an extension to a new state
180
181	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		// Get current state
187		let current_state = self
188			.get_state(extension_id)
189			.await
190			.ok_or_else(|| anyhow::anyhow!("Extension not found: {}", extension_id))?;
191
192		// Clone event for later use before moving it
193		let event_clone = event.clone();
194
195		// Determine new state based on event
196		let new_state = self.determine_next_state(current_state, event)?;
197
198		// Perform state transition (in real implementation, this would call extension)
199		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		// Record event
205		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	/// Determine the next state based on current state and event
234	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	/// Perform actual state transition
259	async fn perform_state_transition(
260		&self,
261		extension_id:&str,
262		event:LifecycleEvent,
263		new_state:LifecycleState,
264	) -> Result<()> {
265		// In real implementation, this would:
266		// 1. Call the extension's lifecycle handler
267		// 2. Handle any errors
268		// 3. Rollback on failure
269
270		dev_log!(
271			"lifecycle",
272			"Performing state transition for extension {}: {:?} -> {:?}",
273			extension_id,
274			event,
275			new_state
276		);
277
278		// Update state
279		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	/// Trigger a lifecycle event for an extension
297
298	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	/// Get event history
307	pub async fn get_event_history(&self) -> Vec<LifecycleEventRecord> { self.event_history.read().await.clone() }
308
309	/// Get event history for a specific extension
310	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	/// Get all registered extensions
321	pub async fn get_registered_extensions(&self) -> Vec<String> {
322		self.handlers.read().await.keys().cloned().collect()
323	}
324
325	/// Get extensions in a specific state
326	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		// Initialize
376		let state = manager.transition("test.ext", LifecycleEvent::Initialize).await.unwrap();
377		assert_eq!(state, LifecycleState::Initializing);
378
379		// Start
380		let state = manager.transition("test.ext", LifecycleEvent::Start).await.unwrap();
381		assert_eq!(state, LifecycleState::Running);
382
383		// Stop
384		let state = manager.transition("test.ext", LifecycleEvent::Stop).await.unwrap();
385		assert_eq!(state, LifecycleState::Stopping);
386	}
387}