coerce/persistent/
failure.rs

1use crate::actor::context::ActorContext;
2
3use std::fmt;
4use std::fmt::{Display, Formatter};
5use std::time::Duration;
6
7#[derive(Copy, Clone)]
8pub enum RecoveryFailurePolicy {
9    Retry(Retry),
10    StopActor,
11    Panic,
12}
13
14#[derive(Copy, Clone)]
15pub enum PersistFailurePolicy {
16    Retry(Retry),
17    ReturnErr,
18    StopActor,
19    Panic,
20}
21
22#[derive(Copy, Clone)]
23pub enum Retry {
24    UntilSuccess {
25        delay: Option<Duration>,
26    },
27    MaxAttempts {
28        max_attempts: usize,
29        delay: Option<Duration>,
30    },
31}
32
33pub(crate) async fn should_retry(ctx: &mut ActorContext, attempts: &usize, retry: Retry) -> bool {
34    match retry {
35        Retry::UntilSuccess { delay } => {
36            if let Some(delay) = delay {
37                tokio::time::sleep(delay).await;
38            }
39        }
40
41        Retry::MaxAttempts {
42            max_attempts,
43            delay,
44        } => {
45            if attempts >= &max_attempts {
46                ctx.stop(None);
47                return false;
48            }
49
50            if let Some(delay) = delay {
51                tokio::time::sleep(delay).await;
52            }
53        }
54    }
55    return true;
56}
57
58impl Display for RecoveryFailurePolicy {
59    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
60        match &self {
61            RecoveryFailurePolicy::StopActor => write!(f, "StopActor"),
62            RecoveryFailurePolicy::Retry(r) => write!(f, "Retry({})", r),
63            RecoveryFailurePolicy::Panic => write!(f, "Panic"),
64        }
65    }
66}
67
68impl Display for PersistFailurePolicy {
69    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
70        match &self {
71            PersistFailurePolicy::StopActor => write!(f, "StopActor"),
72            PersistFailurePolicy::Retry(r) => write!(f, "Retry({})", r),
73            PersistFailurePolicy::Panic => write!(f, "Panic"),
74            PersistFailurePolicy::ReturnErr => write!(f, "ReturnErr"),
75        }
76    }
77}
78
79impl Display for Retry {
80    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
81        match &self {
82            Retry::UntilSuccess { delay } => {
83                if let Some(delay) = delay.as_ref() {
84                    write!(f, "UntilSuccess(delay={} millis)", delay.as_millis())
85                } else {
86                    write!(f, "UntilSuccess(delay=None)")
87                }
88            }
89
90            Retry::MaxAttempts {
91                max_attempts,
92                delay,
93            } => {
94                if let Some(delay) = delay.as_ref() {
95                    write!(
96                        f,
97                        "MaxAttempts(max_attempts={}, delay={} millis)",
98                        max_attempts,
99                        delay.as_millis()
100                    )
101                } else {
102                    write!(f, "MaxAttempts(max_attempts={}, delay=None)", max_attempts)
103                }
104            }
105        }
106    }
107}
108
109impl Default for RecoveryFailurePolicy {
110    fn default() -> Self {
111        RecoveryFailurePolicy::Retry(Retry::UntilSuccess {
112            delay: Some(Duration::from_millis(500)),
113        })
114    }
115}
116
117impl Default for PersistFailurePolicy {
118    fn default() -> Self {
119        PersistFailurePolicy::Retry(Retry::UntilSuccess {
120            delay: Some(Duration::from_millis(500)),
121        })
122    }
123}