1use std::thread;
2use std::time::Duration;
3
4use crate::backoff::Backoff;
5use crate::error::Error;
6
7pub fn retry<F, B, T, E>(backoff: B, op: F) -> Result<T, Error<E>>
24where
25 F: FnMut() -> Result<T, Error<E>>,
26 B: Backoff,
27{
28 let mut retry = Retry {
29 backoff,
30 notify: NoopNotify,
31 sleep: ThreadSleep,
32 };
33
34 retry.retry_notify(op)
35}
36
37pub fn retry_notify<F, B, N, T, E>(backoff: B, op: F, notify: N) -> Result<T, Error<E>>
57where
58 F: FnMut() -> Result<T, Error<E>>,
59 B: Backoff,
60 N: Notify<E>,
61{
62 let mut retry = Retry {
63 backoff,
64 notify,
65 sleep: ThreadSleep,
66 };
67
68 retry.retry_notify(op)
69}
70
71struct Retry<B, N, S> {
72 backoff: B,
73 notify: N,
74 sleep: S,
75}
76
77impl<B, N, S> Retry<B, N, S> {
78 pub fn retry_notify<F, T, E>(&mut self, mut op: F) -> Result<T, Error<E>>
79 where
80 F: FnMut() -> Result<T, Error<E>>,
81 B: Backoff,
82 N: Notify<E>,
83 S: Sleep,
84 {
85 self.backoff.reset();
86
87 loop {
88 let err = match op() {
89 Ok(v) => return Ok(v),
90 Err(err) => err,
91 };
92
93 let (err, next) = match err {
94 Error::Permanent(err) => return Err(Error::Permanent(err)),
95 Error::Transient { err, retry_after } => {
96 match retry_after.or_else(|| self.backoff.next_backoff()) {
97 Some(next) => (err, next),
98 None => return Err(Error::transient(err)),
99 }
100 }
101 };
102
103 self.notify.notify(err, next);
104
105 self.sleep.sleep(next);
106 }
107 }
108}
109
110trait Sleep {
111 fn sleep(&mut self, dur: Duration);
112}
113
114struct ThreadSleep;
115
116impl Sleep for ThreadSleep {
117 fn sleep(&mut self, dur: Duration) {
118 thread::sleep(dur);
119 }
120}
121
122pub trait Notify<E> {
124 fn notify(&mut self, err: E, duration: Duration);
125}
126
127impl<E, F> Notify<E> for F
128where
129 F: FnMut(E, Duration),
130{
131 fn notify(&mut self, err: E, duration: Duration) {
132 self(err, duration)
133 }
134}
135
136#[derive(Debug, Clone, Copy)]
138pub struct NoopNotify;
139
140impl<E> Notify<E> for NoopNotify {
141 fn notify(&mut self, _: E, _: Duration) {}
142}