integrate docker and implement state tracking for server lifecycle management

This commit is contained in:
2026-02-02 17:00:32 +01:00
parent 84b56a163a
commit 753d9e1e64
10 changed files with 756 additions and 93 deletions

109
src/state.rs Normal file
View File

@@ -0,0 +1,109 @@
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()
}
}