feat(shipote): collision detection + stats history server-side (fase O)
- Flow socket names usan pipeline_id full (ULID 26 chars) + edge_idx. Cero colisiones entre pipelines (ULID es único global). Fallback con suffix -N si el path existe (cap 1000 retries). - WorkspaceState.stats_history (VecDeque cap 64) — workspace_stats appendea cada call. API workspace_stats_history(id, tail). Protocol WorkspaceStatsHistory. Shell pide history al primer probe → sparkline hidratada al boot, sobrevive restart del shell. 84 tests pasan (ente-incarnate 16, nouser-core 27, shipote-card 8, shipote-core 25, shipote-discern 5, yahweh-provider-fs 3). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -465,6 +465,31 @@ async fn dispatch(
|
||||
},
|
||||
},
|
||||
|
||||
Request::WorkspaceStatsHistory { workspace, tail } => {
|
||||
match mgr.workspace_stats_history(workspace, tail).await {
|
||||
Some(samples) => {
|
||||
let mapped: Vec<WorkspaceStatsInfo> = samples
|
||||
.into_iter()
|
||||
.map(|s| WorkspaceStatsInfo {
|
||||
commands_alive: s.commands_alive,
|
||||
commands_total: s.commands_total,
|
||||
rss_bytes: s.rss_bytes,
|
||||
rss_peak_bytes: s.rss_peak_bytes,
|
||||
cpu_usec: s.cpu_usec,
|
||||
cpu_percent: s.cpu_percent,
|
||||
cpu_cores: s.cpu_cores,
|
||||
source: s.source,
|
||||
uptime_ms: s.uptime_ms,
|
||||
})
|
||||
.collect();
|
||||
Response::WorkspaceStatsHistory { samples: mapped }
|
||||
}
|
||||
None => Response::Error {
|
||||
message: format!("workspace {workspace} not found"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Request::WorkspaceFullSummary { workspace } => {
|
||||
let stats = match mgr.workspace_stats(workspace).await {
|
||||
Some(s) => WorkspaceStatsInfo {
|
||||
|
||||
Reference in New Issue
Block a user