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
49    /// Check the policy if a certain request should be retried.
50    ///
51    /// This method is passed a reference to the original request, and either
52    /// the [`Service::Response`] or [`Service::Error`] from the inner service.
53    ///
54    /// If the request should **not** be retried, return `None`.
55    ///
56    /// If the request *should* be retried, return `Some` future of a new
57    /// policy that would apply for the next request attempt.
58    ///
59    /// [`Service::Response`]: crate::Service::Response
60    /// [`Service::Error`]: crate::Service::Error
61    fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future>;
62
63    /// Tries to clone a request before being passed to the inner service.
64    ///
65    /// If the request cannot be cloned, return [`None`].
66    fn clone_request(&self, req: &Req) -> Option<Req>;
67}