Watch
0
0
Fork
You've already forked hyperhive
0

start: log an unreadable applied-rev marker instead of silently treating it as stale

start_many mapped every read error on the marker to None via .ok(), so the
agent went down the rebuild path while the log blamed a stale rev. A missing
marker stays silent; any other error now logs the path and error. Control
flow is unchanged.
This commit is contained in:
atlas 2026-10-16 14:11:19 +02:00 • committed by mara
commit 07456c27f3

View file

@ -291,7 +291,7 @@ pub async fn start_many(
let mut targets = Vec::with_capacity(agents.len());
for agent in agents {
let running = lifecycle::is_running(agent).await;
let stored = std::fs::read_to_string(crate::paths::applied_rev_marker(agent)).ok();
let stored = read_rev_marker(&crate::paths::applied_rev_marker(agent));
let stale = current
.as_ref()
.is_some_and(|rev| stored.as_deref() != Some(rev.as_str()));
@ -305,6 +305,20 @@ pub async fn start_many(
Ok(ids)
}
/// The rev `marker` records, or `None` when there is none. A missing file is
/// the normal never-applied case; any other read error is logged, and the
/// caller still treats the rev as stale.
fn read_rev_marker(marker: &std::path::Path) -> Option<String> {
match std::fs::read_to_string(marker) {
Ok(rev) => Some(rev),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => None,
Err(e) => {
tracing::warn!(path = %marker.display(), error = %e, "start: applied-rev marker unreadable; treating rev as stale");
None
}
}
}
/// Stop `agents` in a **single** DAG. A running agent gets
/// `SetWanted(Off) → [Signal → Drain →](graceful) Reconcile`; a down agent
/// skips the pointless quiesce but keeps the `Reconcile` as the race-up
@ -354,3 +368,19 @@ pub fn pause_many(coord: &Arc<Coordinator>, agents: &[String]) -> anyhow::Result
coord.emit_rebuild_queue_snapshot();
Ok(ids)
}
#[cfg(test)]
mod tests {
use super::read_rev_marker;
#[test]
fn a_rev_marker_reads_as_its_contents_and_none_when_absent_or_unreadable() {
let dir = tempfile::tempdir().unwrap();
let marker = dir.path().join("rev");
assert_eq!(read_rev_marker(&marker), None);
std::fs::write(&marker, "abc").unwrap();
assert_eq!(read_rev_marker(&marker).as_deref(), Some("abc"));
// A directory where the file belongs fails with a non-NotFound error.
assert_eq!(read_rev_marker(dir.path()), None);
}
}