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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EGntTHCW3sEPy1VBRopNNp
This commit is contained in:
2026-08-07 13:11:01 +02:00
co-authored by Claude Opus 5
parent d75d57ff0b
commit 0c8ae3b617
4 changed files with 46 additions and 8 deletions
+3 -5
View File
@@ -48,7 +48,7 @@ pub struct Status {
pub state: ServerState,
pub pid: Option<u32>,
pub port: u16,
pub uptime_secs: Option<u64>,
pub started_at: Option<Instant>,
pub restart_count: u32,
pub last_exit: Option<i32>,
}
@@ -109,13 +109,11 @@ impl<S: Spawner> SupervisorTask<S> {
}
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,
}