1use std::time::Duration;
2
3use futures_retry::{ErrorHandler, RetryPolicy};
4use rand::{Rng, SeedableRng};
5use rand_xorshift::XorShiftRng;
6use rusoto_core::RusotoError;
7
8pub struct RetryHandler {
9 attempt: u8,
10 max_attempts: u8,
11 rng: XorShiftRng,
12}
13
14impl RetryHandler {
15 pub fn new(attempts: u8) -> Self {
16 Self {
17 attempt: 0,
18 max_attempts: attempts,
19 rng: XorShiftRng::from_seed([0; 16]), }
21 }
22}
23
24impl<E> ErrorHandler<RusotoError<E>> for RetryHandler {
25 type OutError = RusotoError<E>;
26
27 fn handle(&mut self, e: RusotoError<E>) -> RetryPolicy<RusotoError<E>> {
28 if self.attempt == self.max_attempts {
29 return RetryPolicy::ForwardError(e);
30 }
31 self.attempt += 1;
32 match e {
33 RusotoError::HttpDispatch(_) | RusotoError::Unknown(_) => {
34 let jitter: u64 = self.rng.gen_range(10, 50);
35 let backoff = jitter + (self.attempt as u64 * 10);
36 RetryPolicy::WaitRetry(Duration::from_millis(backoff))
37 }
38 _ => RetryPolicy::ForwardError(e),
39 }
40 }
41
42 fn ok(&mut self) {
43 self.attempt = 0;
44 }
45}