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
use crate::RetryPolicy;

/// An error handler trait.
///
/// Please note that this trait is implemented for any `FnMut` closure with a compatible signature,
/// so for some simple cases you might simply use a closure instead of creating your own type and
/// implementing this trait for it.
///
/// Here's an example of an error handler that counts *consecutive* error attempts.
///
/// ```
/// use futures_retry::{ErrorHandler, RetryPolicy};
/// use std::io;
/// use std::time::Duration;
///
/// pub struct CustomHandler {
///     attempt: usize,
///     max_attempts: usize,
/// }
///
/// impl CustomHandler {
///     pub fn new(attempts: usize) -> Self {
///         Self {
///             attempt: 0,
///             max_attempts: attempts,
///         }
///     }
/// }
///
/// impl ErrorHandler<io::Error> for CustomHandler {
///     type OutError = io::Error;
///
///     fn handle(&mut self, e: io::Error) -> RetryPolicy<io::Error> {
///         if self.attempt == self.max_attempts {
///             eprintln!("No attempts left");
///             return RetryPolicy::ForwardError(e);
///         }
///         self.attempt += 1;
///         match e.kind() {
///             io::ErrorKind::ConnectionRefused => RetryPolicy::WaitRetry(Duration::from_secs(1)),
///             io::ErrorKind::TimedOut => RetryPolicy::Repeat,
///             _ => RetryPolicy::ForwardError(e),
///         }
///     }
///
///     fn ok(&mut self) {
///         self.attempt = 0;
///     }
/// }
/// #
/// # fn main() {}
/// ```
pub trait ErrorHandler<InError> {
    /// An error that the `handle` function will produce.
    type OutError;

    /// Handles an error.
    ///
    /// Refer to the [`RetryPolicy`](enum.RetryPolicy.html) type to understand what this method
    /// might return.
    fn handle(&mut self, _: InError) -> RetryPolicy<Self::OutError>;

    /// This method is called on a successful execution (before returning an item) of the underlying
    /// future/stream.
    ///
    /// One can use this method to reset an internal state, like a consecutive errors counter for
    /// example.
    ///
    /// By default the method is a no-op.
    fn ok(&mut self) {}
}

impl<InError, F, OutError> ErrorHandler<InError> for F
where
    F: FnMut(InError) -> RetryPolicy<OutError>,
{
    type OutError = OutError;

    fn handle(&mut self, e: InError) -> RetryPolicy<OutError> {
        (self)(e)
    }
}