use std::time::Duration;
use super::declarations::QueueDeclaration;
use super::taxonomy::QueueServiceReason;
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct PoolCensus {
pub workers_in_pool: usize,
pub workers_serving_activity: usize,
pub compatible_workers: usize,
pub last_compatible_poller_age: Option<Duration>,
}
impl PoolCensus {
#[must_use]
pub const fn is_served(&self) -> bool {
self.compatible_workers > 0
}
}
#[must_use]
pub fn classify(declaration: QueueDeclaration, census: &PoolCensus) -> Option<QueueServiceReason> {
if census.is_served() {
return None;
}
if declaration == QueueDeclaration::NotDeclared {
return Some(QueueServiceReason::NoQueueDeclaration);
}
if census.workers_in_pool > 0 {
return Some(QueueServiceReason::PollersIncompatible);
}
Some(QueueServiceReason::NoLivePollers)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_served_address_is_not_classified() {
let census = PoolCensus {
workers_in_pool: 1,
workers_serving_activity: 1,
compatible_workers: 1,
last_compatible_poller_age: Some(Duration::ZERO),
};
assert_eq!(classify(QueueDeclaration::Declared, &census), None);
assert_eq!(classify(QueueDeclaration::NotDeclared, &census), None);
}
#[test]
fn an_undeclared_queue_is_structural() {
assert_eq!(
classify(QueueDeclaration::NotDeclared, &PoolCensus::default()),
Some(QueueServiceReason::NoQueueDeclaration)
);
}
#[test]
fn an_empty_pool_on_a_declared_queue_has_no_live_pollers() {
assert_eq!(
classify(QueueDeclaration::Declared, &PoolCensus::default()),
Some(QueueServiceReason::NoLivePollers)
);
}
#[test]
fn an_unknowable_declaration_never_produces_a_structural_refusal() {
assert_eq!(
classify(QueueDeclaration::Unknown, &PoolCensus::default()),
Some(QueueServiceReason::NoLivePollers)
);
}
#[test]
fn pollers_that_do_not_cover_the_activity_are_incompatible() {
let census = PoolCensus {
workers_in_pool: 2,
workers_serving_activity: 0,
compatible_workers: 0,
last_compatible_poller_age: None,
};
assert_eq!(
classify(QueueDeclaration::Declared, &census),
Some(QueueServiceReason::PollersIncompatible)
);
}
#[test]
fn pollers_off_the_pinned_node_are_incompatible() {
let census = PoolCensus {
workers_in_pool: 1,
workers_serving_activity: 1,
compatible_workers: 0,
last_compatible_poller_age: Some(Duration::from_secs(9)),
};
assert_eq!(
classify(QueueDeclaration::Declared, &census),
Some(QueueServiceReason::PollersIncompatible)
);
}
}