Watch
0
0
Fork
You've already forked hyperhive
0

lifecycle: leak the stop-failed warning kind once per agent

Closes #6096
This commit is contained in:
atlas 2026-11-06 03:07:50 +01:00 • committed by mara
commit 32af7e0639
2 changed files with 39 additions and 6 deletions

View file

@ -325,11 +325,20 @@ fn stop_failed_guards()
REG.get_or_init(|| std::sync::Mutex::new(std::collections::HashMap::new()))
}
/// Leak a per-agent warning `kind`. Agent names are a small, bounded set —
/// leaking one short string per distinct agent that ever hits a stop
/// failure is cheap.
fn static_stop_kind(name: &str) -> &'static str {
Box::leak(format!("agent_stop_failed_{name}").into_boxed_str())
/// The per-agent warning `kind`, leaked on the first call for a name and
/// returned unchanged afterwards, whether or not the warning was cleared in
/// between. The leak is one short string per distinct agent name.
fn stop_kind(name: &str) -> &'static str {
static KINDS: std::sync::OnceLock<
std::sync::Mutex<std::collections::HashMap<String, &'static str>>,
> = std::sync::OnceLock::new();
let mut kinds = KINDS
.get_or_init(|| std::sync::Mutex::new(std::collections::HashMap::new()))
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
kinds
.entry(name.to_owned())
.or_insert_with(|| Box::leak(format!("agent_stop_failed_{name}").into_boxed_str()))
}
/// Stop `name`'s container. See `hive-priv`'s `stop_and_release` for why
@ -356,7 +365,7 @@ pub async fn kill(name: &str) -> Result<()> {
guards.insert(
name.to_owned(),
crate::warnings::set_warning(
static_stop_kind(name),
stop_kind(name),
"crit",
format!("{name}: stop failed — {e}"),
),

View file

@ -422,3 +422,27 @@ fn a_build_without_a_log_row_has_an_empty_build_id() {
assert_eq!(field(&logged[0].1, "build_id"), Some(""));
assert_eq!(field(&logged[0].1, "agent"), Some("alice"));
}
#[test]
fn stop_kind_is_leaked_once_per_agent() {
let first = stop_kind("stopkind-a");
assert_eq!(first, "agent_stop_failed_stopkind-a");
assert!(std::ptr::eq(first, stop_kind("stopkind-a")));
assert!(!std::ptr::eq(first, stop_kind("stopkind-b")));
}
#[test]
fn stop_kind_survives_a_clean_stop_between_failures() {
let failed = |guards: &mut std::collections::HashMap<_, _>| {
let kind = stop_kind("stopkind-c");
guards.insert(
"stopkind-c".to_owned(),
crate::warnings::set_warning(kind, "crit", "stop failed"),
);
kind
};
let mut guards = std::collections::HashMap::new();
let first = failed(&mut guards);
guards.remove("stopkind-c");
assert!(std::ptr::eq(first, failed(&mut guards)));
}