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
20	/// Extension is being started
21	Start,
22
23	/// Extension is being stopped
24	Stop,
25
26	/// Extension is being disposed
27	Dispose,
28
29	/// Extension is reloading (hot reload)
30	Reload,
31
32	/// Extension is being suspended
33	Suspend,
34
35	/// Extension is being resumed
36	Resume,
37
38	/// Custom lifecycle event
39	Custom(String),
40}
41
42/// Lifecycle state for extensions
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
44pub enum LifecycleState {
45	/// Extension has been created but not initialized
46	Created,
47
48	/// Extension is being initialized
49	Initializing,
50
51	/// Extension is active and running
52	Running,
53
54	/// Extension is being suspended
55	Suspending,
56
57	/// Extension is suspended
58	Suspended,
59
60	/// Extension is being stopped
61	Stopping,
62
63	/// Extension has been stopped
64	Stopped,
65
66	/// Extension is being disposed
67	Disposing,
68
69	/// Extension has been disposed
70	Disposed,
71
72	/// Extension is in an error state
73	Error,
74}
75
76/// Lifecycle event handler callback
77#[allow(dead_code)]
78type LifecycleEventHandler = fn(&str, LifecycleEvent) -> Result<()>;
79
80/// Lifecycle manager for extension lifecycle
81pub struct LifecycleManager {
82	/// Event handlers
83	handlers:Arc<RwLock<HashMap<String, LifecycleHandlerInfo>>>,
84
85	/// Extension states
86	states:Arc<RwLock<HashMap<String, LifecycleState>>>,
87
88	/// Event history
89	event_history:Arc<RwLock<Vec<LifecycleEventRecord>>>,
90}
91
92/// Information about a lifecycle handler
93#[derive(Debug, Clone)]
94struct LifecycleHandlerInfo {
95	/// Extension ID
96	#[allow(dead_code)]
97	extension_id:String,
98
99	/// Current state
100	state:LifecycleState,
101
102	/// Supported events
103	#[allow(dead_code)]
104	supported_events:Vec<LifecycleEvent>,
105
106	/// Last state change timestamp
107	last_state_change:Option<u64>,
108}
109
110/// Record of a lifecycle event
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct LifecycleEventRecord {
113	/// Extension ID
114	pub extension_id:String,
115
116	/// Event that occurred
117	pub event:LifecycleEvent,
118
119	/// Previous state
120	pub previous_state:LifecycleState,
121
122	/// New state
123	pub new_state:LifecycleState,
124
125	/// Timestamp
126	pub timestamp:u64,
127
128	/// Duration in milliseconds
129	pub duration_ms:u64,
130
131	/// Success flag
132	pub success:bool,
133
134	/// Error message (if failed)
135	pub error:Option<String>,
136}
137
138impl LifecycleManager {
139	/// Create a new lifecycle manager
140	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	/// Register an extension for lifecycle management
151
152	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	/// Unregister an extension from lifecycle management
187
188	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	/// Get the current state of an extension
209	pub async fn get_state(&self, extension_id:&str) -> Option<LifecycleState> {
210		self.states.read().await.get(extension_id).copied()
211	}
212
213	/// Transition an extension to a new state
214
215	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		// Get current state
221		let current_state = self
222			.get_state(extension_id)
223			.await
224			.ok_or_else(|| anyhow::anyhow!("Extension not found: {}", extension_id))?;
225
226		// Clone event for later use before moving it
227		let event_clone = event.clone();
228
229		// Determine new state based on event
230		let new_state = self.determine_next_state(current_state, event)?;
231
232		// Perform state transition (in real implementation, this would call extension)
233		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		// Record event
239		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	/// Determine the next state based on current state and event
275	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	/// Perform actual state transition
310	async fn perform_state_transition(
311		&self,
312
313		extension_id:&str,
314
315		event:LifecycleEvent,
316
317		new_state:LifecycleState,
318	) -> Result<()> {
319		// In real implementation, this would:
320		// 1. Call the extension's lifecycle handler
321		// 2. Handle any errors
322		// 3. Rollback on failure
323
324		dev_log!(
325			"lifecycle",
326			"Performing state transition for extension {}: {:?} -> {:?}",
327			extension_id,
328			event,
329			new_state
330		);
331
332		// Update state
333		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	/// Trigger a lifecycle event for an extension
354
355	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	/// Get event history
364	pub async fn get_event_history(&self) -> Vec<LifecycleEventRecord> { self.event_history.read().await.clone() }
365
366	/// Get event history for a specific extension
367	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	/// Get all registered extensions
378	pub async fn get_registered_extensions(&self) -> Vec<String> {
379		self.handlers.read().await.keys().cloned().collect()
380	}
381
382	/// Get extensions in a specific state
383	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		// Initialize
440		let state = manager.transition("test.ext", LifecycleEvent::Initialize).await.unwrap();
441
442		assert_eq!(state, LifecycleState::Initializing);
443
444		// Start
445		let state = manager.transition("test.ext", LifecycleEvent::Start).await.unwrap();
446
447		assert_eq!(state, LifecycleState::Running);
448
449		// Stop
450		let state = manager.transition("test.ext", LifecycleEvent::Stop).await.unwrap();
451
452		assert_eq!(state, LifecycleState::Stopping);
453	}
454}