lifecycle: leak the stop-failed warning kind once per agent
Closes #6096
This commit is contained in:
parent
18e4f195e5
commit
32af7e0639
2 changed files with 39 additions and 6 deletions
|
|
@ -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}"),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue