use crate::events::HedgeEvent;
use crate::layer::HedgeLayer;
use std::sync::Arc;
use std::time::Duration;
use tower_resilience_core::{EventListener, EventListeners};
#[derive(Clone)]
pub enum HedgeDelay {
Fixed(Duration),
Immediate,
Dynamic(Arc<dyn Fn(usize) -> Duration + Send + Sync>),
}
impl HedgeDelay {
pub fn get_delay(&self, attempt: usize) -> Option<Duration> {
match self {
HedgeDelay::Fixed(d) => Some(*d),
HedgeDelay::Immediate => Some(Duration::ZERO),
HedgeDelay::Dynamic(f) => Some(f(attempt)),
}
}
}
impl Default for HedgeDelay {
fn default() -> Self {
HedgeDelay::Fixed(Duration::from_secs(1))
}
}
#[derive(Clone)]
pub struct HedgeConfig {
pub(crate) name: Option<String>,
pub(crate) max_hedged_attempts: usize,
pub(crate) delay: HedgeDelay,
pub(crate) listeners: EventListeners<HedgeEvent>,
}
impl Default for HedgeConfig {
fn default() -> Self {
Self {
name: None,
max_hedged_attempts: 2,
delay: HedgeDelay::default(),
listeners: EventListeners::default(),
}
}
}
pub struct HedgeConfigBuilder {
config: HedgeConfig,
}
impl Default for HedgeConfigBuilder {
fn default() -> Self {
Self::new()
}
}
impl HedgeConfigBuilder {
pub fn new() -> Self {
Self {
config: HedgeConfig::default(),
}
}
pub fn name(mut self, name: impl Into<String>) -> Self {
self.config.name = Some(name.into());
self
}
pub fn max_hedged_attempts(mut self, n: usize) -> Self {
self.config.max_hedged_attempts = n.max(1);
self
}
pub fn delay(mut self, delay: Duration) -> Self {
self.config.delay = HedgeDelay::Fixed(delay);
self
}
pub fn no_delay(mut self) -> Self {
self.config.delay = HedgeDelay::Immediate;
self
}
pub fn delay_fn<F>(mut self, f: F) -> Self
where
F: Fn(usize) -> Duration + Send + Sync + 'static,
{
self.config.delay = HedgeDelay::Dynamic(Arc::new(f));
self
}
pub fn on_event<L>(mut self, listener: L) -> Self
where
L: EventListener<HedgeEvent> + 'static,
{
self.config.listeners.add(listener);
self
}
pub fn build(self) -> HedgeLayer {
HedgeLayer::from_config(self.config)
}
}