tower_retry/
policy.rs

1use std::future::Future;
2
3/// A "retry policy" to classify if a request should be retried.
4///
5/// # Example
6///
7/// ```
8/// use tower_retry::Policy;
9/// use futures_util::future;
10///
11/// type Req = String;
12/// type Res = String;
13///
14/// struct Attempts(usize);
15///
16/// impl<E> Policy<Req, Res, E> for Attempts {
17///     type Future = future::Ready<Self>;
18///
19///     fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future> {
20///         match result {
21///             Ok(_) => {
22///                 // Treat all `Response`s as success,
23///                 // so don't retry...
24///                 None
25///             },
26///             Err(_) => {
27///                 // Treat all errors as failures...
28///                 // But we limit the number of attempts...
29///                 if self.0 > 0 {
30///                     // Try again!
31///                     Some(future::ready(Attempts(self.0 - 1)))
32///                 } else {
33///                     // Used all our attempts, no retry...
34///                     None
35///                 }
36///             }
37///         }
38///     }
39///
40///     fn clone_request(&self, req: &Req) -> Option<Req> {
41///         Some(req.clone())
42///     }
43/// }
44/// ```
45pub trait Policy<Req, Res, E>: Sized {
46    /// The `Future` type returned by `Policy::retry()`.
47    type Future: Future<Output = Self>;
48    /// Check the policy if a certain request should be retried.
49    ///
50    /// This method is passed a reference to the original request, and either
51    /// the `Service::Response` or `Service::Error` from the inner service.
52    ///
53    /// If the request should **not** be retried, return `None`.
54    ///
55    /// If the request *should* be retried, return `Some` future of a new
56    /// policy that would apply for the next request attempt.
57    fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future>;
58    /// Tries to clone a request before being passed to the inner service.
59    ///
60    /// If the request cannot be cloned, return `None`.
61    fn clone_request(&self, req: &Req) -> Option<Req>;
62}