110 lines
2.7 KiB
Rust
110 lines
2.7 KiB
Rust
use std::sync::Arc;
|
|
use tokio::sync::RwLock;
|
|
use tokio::time::Instant;
|
|
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct StartupMetrics {
|
|
pub total_startups: u32,
|
|
pub total_duration_secs: u64,
|
|
}
|
|
|
|
impl StartupMetrics {
|
|
pub fn record_startup(&mut self, duration_secs: u64) {
|
|
self.total_startups += 1;
|
|
self.total_duration_secs += duration_secs;
|
|
}
|
|
|
|
pub fn average_startup_time(&self) -> Option<u64> {
|
|
if self.total_startups == 0 {
|
|
None
|
|
} else {
|
|
Some(self.total_duration_secs / self.total_startups as u64)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum ServerState {
|
|
Unknown,
|
|
Stopped,
|
|
Starting {
|
|
started_at: Instant,
|
|
},
|
|
Running {
|
|
rcon_connected_at: Instant,
|
|
},
|
|
Stopping {
|
|
stop_requested_at: Instant,
|
|
},
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct SharedServerState {
|
|
state: Arc<RwLock<ServerState>>,
|
|
metrics: Arc<RwLock<StartupMetrics>>,
|
|
}
|
|
|
|
impl SharedServerState {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
state: Arc::new(RwLock::new(ServerState::Unknown)),
|
|
metrics: Arc::new(RwLock::new(StartupMetrics::default())),
|
|
}
|
|
}
|
|
|
|
pub async fn get(&self) -> ServerState {
|
|
self.state.read().await.clone()
|
|
}
|
|
|
|
pub async fn set(&self, new_state: ServerState) {
|
|
let mut state = self.state.write().await;
|
|
let old_state = state.clone();
|
|
*state = new_state.clone();
|
|
|
|
if old_state != new_state {
|
|
println!("State transition: {:?} -> {:?}", old_state, new_state);
|
|
}
|
|
}
|
|
|
|
pub async fn transition_to_starting(&self) {
|
|
self.set(ServerState::Starting {
|
|
started_at: Instant::now(),
|
|
}).await;
|
|
}
|
|
|
|
pub async fn transition_to_running(&self) {
|
|
self.set(ServerState::Running {
|
|
rcon_connected_at: Instant::now(),
|
|
}).await;
|
|
}
|
|
|
|
pub async fn transition_to_stopping(&self) {
|
|
self.set(ServerState::Stopping {
|
|
stop_requested_at: Instant::now(),
|
|
}).await;
|
|
}
|
|
|
|
pub async fn transition_to_stopped(&self) {
|
|
self.set(ServerState::Stopped).await;
|
|
}
|
|
|
|
pub async fn record_startup_duration(&self, duration_secs: u64) {
|
|
let mut metrics = self.metrics.write().await;
|
|
metrics.record_startup(duration_secs);
|
|
println!("Server startup took {}s (avg: {}s over {} startups)",
|
|
duration_secs,
|
|
metrics.average_startup_time().unwrap_or(0),
|
|
metrics.total_startups);
|
|
}
|
|
|
|
pub async fn get_average_startup_time(&self) -> Option<u64> {
|
|
self.metrics.read().await.average_startup_time()
|
|
}
|
|
}
|
|
|
|
impl Default for SharedServerState {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|