1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#[cfg(any(feature = "tokio", feature = "async-std"))]
pub mod r#async;
use std::thread;
use std::time::Duration;
use crate::backoff::Backoff;
use crate::error::Error;
pub trait Operation<T, E> {
fn call_op(&mut self) -> Result<T, Error<E>>;
fn retry<B>(&mut self, backoff: &mut B) -> Result<T, Error<E>>
where
B: Backoff,
{
let nop = |_, _| ();
self.retry_notify(backoff, nop)
}
fn retry_notify<B, N>(&mut self, backoff: &mut B, mut notify: N) -> Result<T, Error<E>>
where
N: Notify<E>,
B: Backoff,
{
backoff.reset();
loop {
let err = match self.call_op() {
Ok(v) => return Ok(v),
Err(err) => err,
};
let err = match err {
Error::Permanent(err) => return Err(Error::Permanent(err)),
Error::Transient(err) => err,
};
let next = match backoff.next_backoff() {
Some(next) => next,
None => return Err(Error::Transient(err)),
};
notify.notify(err, next);
thread::sleep(next);
}
}
}
impl<T, E, F> Operation<T, E> for F
where
F: FnMut() -> Result<T, Error<E>>,
{
fn call_op(&mut self) -> Result<T, Error<E>> {
self()
}
}
pub trait Notify<E> {
fn notify(&mut self, err: E, duration: Duration);
}
impl<E, F> Notify<E> for F
where
F: FnMut(E, Duration),
{
fn notify(&mut self, err: E, duration: Duration) {
self(err, duration)
}
}
#[derive(Debug, Clone, Copy)]
pub struct NoopNotify;
impl<E> Notify<E> for NoopNotify {
fn notify(&mut self, _: E, _: Duration) {}
}