From 0c8ae3b61725abbf9e81e63f2e4c00a151fd4b8d Mon Sep 17 00:00:00 2001 From: Anders Olsson Date: Fri, 7 Aug 2026 13:11:01 +0200 Subject: [PATCH] fix(supervisor): compute uptime at read time, not publish time set_state computed uptime_secs from started_at.elapsed() and pushed the result into the watch channel. do_start sets started_at immediately before calling set_state(Running), so the published value was always ~0, and the list/status handlers copied that frozen snapshot straight out. A server that stayed healthy reported 0s forever, because the value was only recomputed on the next state transition. Status now carries started_at (an Instant, in-process only) and the handlers derive uptime_secs when they build ServerSummary. The wire type is unchanged. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01EGntTHCW3sEPy1VBRopNNp --- crates/xy-supervisor/src/supervisor.rs | 8 ++---- crates/xy/src/daemon/handlers.rs | 4 +-- crates/xy/src/daemon/mod.rs | 2 +- crates/xy/tests/uptime.rs | 40 ++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 crates/xy/tests/uptime.rs diff --git a/crates/xy-supervisor/src/supervisor.rs b/crates/xy-supervisor/src/supervisor.rs index 329490c..a32de08 100644 --- a/crates/xy-supervisor/src/supervisor.rs +++ b/crates/xy-supervisor/src/supervisor.rs @@ -48,7 +48,7 @@ pub struct Status { pub state: ServerState, pub pid: Option, pub port: u16, - pub uptime_secs: Option, + pub started_at: Option, pub restart_count: u32, pub last_exit: Option, } @@ -109,13 +109,11 @@ impl SupervisorTask { } fn set_state(&mut self, s: ServerState) { - let uptime_secs = self.started_at.map(|t| t.elapsed().as_secs()); - let _ = self.status_tx.send(Status { state: s, pid: self.current_pid, port: self.cfg.port, - uptime_secs, + started_at: self.started_at, restart_count: self.restart_count, last_exit: self.last_exit, }); @@ -407,7 +405,7 @@ mod tests { state: ServerState::Stopped, pid: None, port: cfg.port, - uptime_secs: None, + started_at: None, restart_count: 0, last_exit: None, } diff --git a/crates/xy/src/daemon/handlers.rs b/crates/xy/src/daemon/handlers.rs index d331308..ad0c888 100644 --- a/crates/xy/src/daemon/handlers.rs +++ b/crates/xy/src/daemon/handlers.rs @@ -170,7 +170,7 @@ async fn list(reg: &Registry) -> Result, ApiError> { state: s.state, pid: s.pid, port: s.port, - uptime_secs: s.uptime_secs, + uptime_secs: s.started_at.map(|t| t.elapsed().as_secs()), restart_count: s.restart_count, last_exit: s.last_exit, }); @@ -195,7 +195,7 @@ async fn status(reg: &Registry, name: &str) -> Result { state: s.state, pid: s.pid, port: s.port, - uptime_secs: s.uptime_secs, + uptime_secs: s.started_at.map(|t| t.elapsed().as_secs()), restart_count: s.restart_count, last_exit: s.last_exit, }, diff --git a/crates/xy/src/daemon/mod.rs b/crates/xy/src/daemon/mod.rs index ddcd70a..f243fa7 100644 --- a/crates/xy/src/daemon/mod.rs +++ b/crates/xy/src/daemon/mod.rs @@ -43,7 +43,7 @@ pub fn spawn_supervisor(paths: &Paths, cfg: ServerConfig) -> Result