use std::time::{Duration, Instant};
use super::{BackoffStrategy, StrategyFactory};
pub struct ThresholdBucketsFactory {
pub buckets: Vec<(usize, Duration)>,
pub monitoring_period: Duration,
}
impl Default for ThresholdBucketsFactory {
fn default() -> Self {
Self {
buckets: vec![
(1, Duration::from_secs(5)),
(5, Duration::from_secs(10)),
(10, Duration::from_secs(30)),
],
monitoring_period: Duration::from_secs(60),
}
}
}
impl StrategyFactory for ThresholdBucketsFactory {
type Strategy = ThresholdBucketsBackoff;
fn create_strategy(&self) -> Self::Strategy {
ThresholdBucketsBackoff {
buckets: self.buckets.clone(),
monitoring_period: self.monitoring_period,
failures: Vec::new(),
}
}
}
pub struct ThresholdBucketsBackoff {
buckets: Vec<(usize, Duration)>,
monitoring_period: Duration,
failures: Vec<Instant>,
}
impl BackoffStrategy for ThresholdBucketsBackoff {
fn add_failure(&mut self) {
self.failures.push(Instant::now());
self.prune_failures();
}
fn next_backoff(&self) -> Duration {
let mut backoff = Duration::from_secs(0);
for (threshold, duration) in &self.buckets {
if self.failures.len() >= *threshold {
backoff = *duration;
}
}
backoff
}
}
impl ThresholdBucketsBackoff {
fn prune_failures(&mut self) {
self.failures
.retain(|instant| instant.elapsed() < self.monitoring_period);
}
}