use std::time::Duration;
use crate::identity::Run;
use crate::record::Record;
use crate::role::Occupancy;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Verdict {
Start,
Wait,
Evict(Record),
EvictAnonymous,
}
#[must_use]
pub fn verdict(occupancy: &Occupancy, mine: Run, waited: Duration, grace: Duration) -> Verdict {
match occupancy {
Occupancy::Free => Verdict::Start,
Occupancy::HeldBy(record) if record.identity.run == mine => Verdict::Wait,
Occupancy::HeldBy(record) => Verdict::Evict(record.clone()),
Occupancy::HeldAnonymously if waited < grace => Verdict::Wait,
Occupancy::HeldAnonymously => Verdict::EvictAnonymous,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::identity::{Compat, Identity};
use crate::record::Tenant;
const GRACE: Duration = Duration::from_secs(15);
const ALMOST_GRACE: Duration = Duration::from_millis(14_999);
const MINE: Run = Run::from_raw(7);
fn held_by(run: u64) -> Occupancy {
Occupancy::HeldBy(Record::new(
Identity::new(Run::from_raw(run), Compat::from_raw(18)),
Tenant {
pid: 4242,
started_at: None,
image: None,
},
))
}
#[test]
fn a_free_role_is_taken_at_once() {
assert_eq!(
verdict(&Occupancy::Free, MINE, Duration::ZERO, GRACE),
Verdict::Start
);
}
#[test]
fn the_supervisors_own_tenant_is_never_evicted() {
assert_eq!(
verdict(&held_by(7), MINE, Duration::from_secs(3600), GRACE),
Verdict::Wait
);
}
#[test]
fn a_tenant_from_a_finished_run_is_evicted_without_waiting() {
let Verdict::Evict(record) = verdict(&held_by(9), MINE, Duration::ZERO, GRACE) else {
panic!("a foreign tenant must be evicted");
};
assert_eq!(record.tenant.pid, 4242);
}
#[test]
fn an_anonymous_tenant_is_given_the_grace_period_first() {
assert_eq!(
verdict(&Occupancy::HeldAnonymously, MINE, Duration::ZERO, GRACE),
Verdict::Wait
);
assert_eq!(
verdict(&Occupancy::HeldAnonymously, MINE, ALMOST_GRACE, GRACE),
Verdict::Wait
);
assert_eq!(
verdict(&Occupancy::HeldAnonymously, MINE, GRACE, GRACE),
Verdict::EvictAnonymous
);
}
}