coerce 0.8.6

Async actor runtime and distributed systems framework
Documentation
use crate::actor::context::ActorContext;

use std::fmt;
use std::fmt::{Display, Formatter};
use std::time::Duration;

#[derive(Copy, Clone)]
pub enum RecoveryFailurePolicy {
    Retry(Retry),
    StopActor,
    Panic,
}

#[derive(Copy, Clone)]
pub enum PersistFailurePolicy {
    Retry(Retry),
    ReturnErr,
    StopActor,
    Panic,
}

#[derive(Copy, Clone)]
pub enum Retry {
    UntilSuccess {
        delay: Option<Duration>,
    },
    MaxAttempts {
        max_attempts: usize,
        delay: Option<Duration>,
    },
}

pub(crate) async fn should_retry(ctx: &mut ActorContext, attempts: &usize, retry: Retry) -> bool {
    match retry {
        Retry::UntilSuccess { delay } => {
            if let Some(delay) = delay {
                tokio::time::sleep(delay).await;
            }
        }

        Retry::MaxAttempts {
            max_attempts,
            delay,
        } => {
            if attempts >= &max_attempts {
                ctx.stop(None);
                return false;
            }

            if let Some(delay) = delay {
                tokio::time::sleep(delay).await;
            }
        }
    }
    return true;
}

impl Display for RecoveryFailurePolicy {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match &self {
            RecoveryFailurePolicy::StopActor => write!(f, "StopActor"),
            RecoveryFailurePolicy::Retry(r) => write!(f, "Retry({})", r),
            RecoveryFailurePolicy::Panic => write!(f, "Panic"),
        }
    }
}

impl Display for PersistFailurePolicy {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match &self {
            PersistFailurePolicy::StopActor => write!(f, "StopActor"),
            PersistFailurePolicy::Retry(r) => write!(f, "Retry({})", r),
            PersistFailurePolicy::Panic => write!(f, "Panic"),
            PersistFailurePolicy::ReturnErr => write!(f, "ReturnErr"),
        }
    }
}

impl Display for Retry {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match &self {
            Retry::UntilSuccess { delay } => {
                if let Some(delay) = delay.as_ref() {
                    write!(f, "UntilSuccess(delay={} millis)", delay.as_millis())
                } else {
                    write!(f, "UntilSuccess(delay=None)")
                }
            }

            Retry::MaxAttempts {
                max_attempts,
                delay,
            } => {
                if let Some(delay) = delay.as_ref() {
                    write!(
                        f,
                        "MaxAttempts(max_attempts={}, delay={} millis)",
                        max_attempts,
                        delay.as_millis()
                    )
                } else {
                    write!(f, "MaxAttempts(max_attempts={}, delay=None)", max_attempts)
                }
            }
        }
    }
}

impl Default for RecoveryFailurePolicy {
    fn default() -> Self {
        RecoveryFailurePolicy::Retry(Retry::UntilSuccess {
            delay: Some(Duration::from_millis(500)),
        })
    }
}

impl Default for PersistFailurePolicy {
    fn default() -> Self {
        PersistFailurePolicy::Retry(Retry::UntilSuccess {
            delay: Some(Duration::from_millis(500)),
        })
    }
}