mcp_runner/server/
lifecycle.rs1use crate::error::{Error, Result};
8use crate::server::{ServerId, ServerStatus};
9use std::collections::HashMap;
10use std::sync::{Arc, Mutex};
11use std::time::Instant;
12use tracing; #[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum ServerLifecycleEvent {
17 Started,
19 Stopped,
21 Failed,
23 Restarted,
25}
26
27#[derive(Debug, Clone)]
32pub struct ServerEvent {
33 pub id: ServerId,
35 pub name: String,
37 pub event: ServerLifecycleEvent,
39 pub timestamp: Instant,
41 pub details: Option<String>,
43}
44
45pub struct ServerLifecycleManager {
50 events: Arc<Mutex<Vec<ServerEvent>>>,
52 statuses: Arc<Mutex<HashMap<ServerId, ServerStatus>>>,
54}
55
56impl ServerLifecycleManager {
57 pub fn new() -> Self {
59 Self {
60 events: Arc::new(Mutex::new(Vec::new())),
61 statuses: Arc::new(Mutex::new(HashMap::new())),
62 }
63 }
64
65 #[tracing::instrument(skip(self), fields(server_id = %id, server_name = %name, event_type = ?event))]
81 pub fn record_event(
82 &self,
83 id: ServerId,
84 name: String,
85 event: ServerLifecycleEvent,
86 details: Option<String>,
87 ) -> Result<()> {
88 tracing::info!(details = ?details, "Recording server lifecycle event");
89 let server_event = ServerEvent {
90 id,
91 name,
92 event,
93 timestamp: Instant::now(),
94 details,
95 };
96
97 {
99 let mut statuses = self.statuses.lock().map_err(|_| {
100 tracing::error!("Failed to lock server statuses");
101 Error::Other("Failed to lock server statuses".to_string())
102 })?;
103
104 let status = match event {
105 ServerLifecycleEvent::Started => ServerStatus::Running,
106 ServerLifecycleEvent::Stopped => ServerStatus::Stopped,
107 ServerLifecycleEvent::Failed => ServerStatus::Failed,
108 ServerLifecycleEvent::Restarted => ServerStatus::Running,
109 };
110
111 tracing::debug!(new_status = ?status, "Updating server status");
112 statuses.insert(id, status);
113 }
114
115 {
117 let mut events = self.events.lock().map_err(|_| {
118 tracing::error!("Failed to lock server events");
119 Error::Other("Failed to lock server events".to_string())
120 })?;
121
122 events.push(server_event);
123 tracing::debug!(total_events = events.len(), "Added event to history");
124
125 if events.len() > 1000 {
127 tracing::trace!("Trimming event history (exceeded 1000 events)");
128 events.remove(0);
129 }
130 }
131
132 tracing::info!("Successfully recorded server event");
133 Ok(())
134 }
135
136 pub fn get_status(&self, id: ServerId) -> Result<ServerStatus> {
148 let statuses = self
149 .statuses
150 .lock()
151 .map_err(|_| Error::Other("Failed to lock server statuses".to_string()))?;
152
153 statuses
154 .get(&id)
155 .copied()
156 .ok_or_else(|| Error::ServerNotFound(format!("{:?}", id)))
157 }
158
159 pub fn get_server_events(
173 &self,
174 id: ServerId,
175 limit: Option<usize>,
176 ) -> Result<Vec<ServerEvent>> {
177 let events = self
178 .events
179 .lock()
180 .map_err(|_| Error::Other("Failed to lock server events".to_string()))?;
181
182 let mut server_events: Vec<ServerEvent> =
183 events.iter().filter(|e| e.id == id).cloned().collect();
184
185 server_events.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));
187
188 if let Some(limit) = limit {
190 server_events.truncate(limit);
191 }
192
193 Ok(server_events)
194 }
195
196 pub fn get_all_events(&self, limit: Option<usize>) -> Result<Vec<ServerEvent>> {
209 let events = self
210 .events
211 .lock()
212 .map_err(|_| Error::Other("Failed to lock server events".to_string()))?;
213
214 let mut all_events = events.clone();
215
216 all_events.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));
218
219 if let Some(limit) = limit {
221 all_events.truncate(limit);
222 }
223
224 Ok(all_events)
225 }
226
227 pub fn clear_events(&self) -> Result<()> {
235 let mut events = self
236 .events
237 .lock()
238 .map_err(|_| Error::Other("Failed to lock server events".to_string()))?;
239
240 events.clear();
241
242 Ok(())
243 }
244}
245
246impl Default for ServerLifecycleManager {
247 fn default() -> Self {
248 Self::new()
249 }
250}