use std::collections::HashMap;
use crate::adapter::net::behavior::meshos::DaemonRef;
use crate::adapter::net::cortex::workflow::ActiveClaim;
#[derive(Debug, Clone, Default)]
pub struct ClaimRegistry {
held: HashMap<DaemonRef, ActiveClaim>,
}
impl ClaimRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, daemon: DaemonRef, claim: ActiveClaim) {
self.held.insert(daemon, claim);
}
pub fn remove(&mut self, daemon: &DaemonRef) -> Option<ActiveClaim> {
self.held.remove(daemon)
}
pub fn get(&self, daemon: &DaemonRef) -> Option<&ActiveClaim> {
self.held.get(daemon)
}
pub fn holds_exclusive(&self, daemon: &DaemonRef) -> bool {
self.held.contains_key(daemon)
}
pub fn len(&self) -> usize {
self.held.len()
}
pub fn is_empty(&self) -> bool {
self.held.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (&DaemonRef, &ActiveClaim)> {
self.held.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn dref(id: u64) -> DaemonRef {
DaemonRef {
id,
name: format!("task/{id}"),
}
}
#[test]
fn insert_get_holds_remove_roundtrip() {
let mut reg = ClaimRegistry::new();
let d = dref(1);
assert!(!reg.holds_exclusive(&d));
assert!(reg.is_empty());
reg.insert(d.clone(), ActiveClaim { island: 0xA0 });
assert!(reg.holds_exclusive(&d), "veto sees the claim once held");
assert_eq!(reg.get(&d).map(|c| c.island), Some(0xA0));
assert_eq!(reg.len(), 1);
let released = reg.remove(&d);
assert_eq!(released.map(|c| c.island), Some(0xA0));
assert!(
!reg.holds_exclusive(&d),
"veto sees no claim after release — daemon becomes migratable",
);
assert!(reg.remove(&d).is_none(), "release is idempotent");
}
#[test]
fn distinct_daemons_hold_independent_claims() {
let mut reg = ClaimRegistry::new();
reg.insert(dref(1), ActiveClaim { island: 0xA0 });
reg.insert(dref(2), ActiveClaim { island: 0xB0 });
assert_eq!(reg.get(&dref(1)).map(|c| c.island), Some(0xA0));
assert_eq!(reg.get(&dref(2)).map(|c| c.island), Some(0xB0));
reg.remove(&dref(1));
assert!(!reg.holds_exclusive(&dref(1)));
assert!(reg.holds_exclusive(&dref(2)));
}
}