use std::time::Duration;
use super::backoff::{BackoffPolicy, InvalidBackoff};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ConvergenceSettings {
pub poll_interval: Duration,
pub target: Duration,
pub backoff: BackoffPolicy,
}
impl Default for ConvergenceSettings {
fn default() -> Self {
Self {
poll_interval: Duration::from_secs(5),
target: Duration::from_secs(30),
backoff: BackoffPolicy::default(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum InvalidSettings {
#[error("convergence.poll_interval must be greater than zero; a zero interval hot-loops")]
ZeroPollInterval,
#[error(
"convergence.target ({target:?}) must be at least convergence.poll_interval \
({poll_interval:?}); a target shorter than the detection delay can never be met"
)]
UnreachableTarget {
poll_interval: Duration,
target: Duration,
},
#[error(transparent)]
Backoff(#[from] InvalidBackoff),
}
impl ConvergenceSettings {
pub fn validate(&self) -> Result<(), InvalidSettings> {
if self.poll_interval.is_zero() {
return Err(InvalidSettings::ZeroPollInterval);
}
if self.target < self.poll_interval {
return Err(InvalidSettings::UnreachableTarget {
poll_interval: self.poll_interval,
target: self.target,
});
}
self.backoff.validate()?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_defaults_are_usable_and_state_a_reachable_target() {
let settings = ConvergenceSettings::default();
assert_eq!(settings.validate(), Ok(()));
assert!(settings.target >= settings.poll_interval);
assert!(settings.poll_interval * 2 <= settings.target);
}
#[test]
fn settings_that_cannot_do_what_they_claim_are_refused() {
assert_eq!(
ConvergenceSettings {
poll_interval: Duration::ZERO,
..Default::default()
}
.validate(),
Err(InvalidSettings::ZeroPollInterval)
);
assert_eq!(
ConvergenceSettings {
poll_interval: Duration::from_secs(10),
target: Duration::from_secs(1),
..Default::default()
}
.validate(),
Err(InvalidSettings::UnreachableTarget {
poll_interval: Duration::from_secs(10),
target: Duration::from_secs(1),
})
);
assert!(matches!(
ConvergenceSettings {
backoff: BackoffPolicy {
initial: Duration::ZERO,
..BackoffPolicy::default()
},
..Default::default()
}
.validate(),
Err(InvalidSettings::Backoff(_))
));
}
}