| use std::future::Future; |
| |
| /// A "retry policy" to classify if a request should be retried. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// use tower::retry::Policy; |
| /// use futures_util::future; |
| /// |
| /// type Req = String; |
| /// type Res = String; |
| /// |
| /// struct Attempts(usize); |
| /// |
| /// impl<E> Policy<Req, Res, E> for Attempts { |
| /// type Future = future::Ready<Self>; |
| /// |
| /// fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future> { |
| /// match result { |
| /// Ok(_) => { |
| /// // Treat all `Response`s as success, |
| /// // so don't retry... |
| /// None |
| /// }, |
| /// Err(_) => { |
| /// // Treat all errors as failures... |
| /// // But we limit the number of attempts... |
| /// if self.0 > 0 { |
| /// // Try again! |
| /// Some(future::ready(Attempts(self.0 - 1))) |
| /// } else { |
| /// // Used all our attempts, no retry... |
| /// None |
| /// } |
| /// } |
| /// } |
| /// } |
| /// |
| /// fn clone_request(&self, req: &Req) -> Option<Req> { |
| /// Some(req.clone()) |
| /// } |
| /// } |
| /// ``` |
| pub trait Policy<Req, Res, E>: Sized { |
| /// The [`Future`] type returned by [`Policy::retry`]. |
| type Future: Future<Output = Self>; |
| |
| /// Check the policy if a certain request should be retried. |
| /// |
| /// This method is passed a reference to the original request, and either |
| /// the [`Service::Response`] or [`Service::Error`] from the inner service. |
| /// |
| /// If the request should **not** be retried, return `None`. |
| /// |
| /// If the request *should* be retried, return `Some` future of a new |
| /// policy that would apply for the next request attempt. |
| /// |
| /// [`Service::Response`]: crate::Service::Response |
| /// [`Service::Error`]: crate::Service::Error |
| fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future>; |
| |
| /// Tries to clone a request before being passed to the inner service. |
| /// |
| /// If the request cannot be cloned, return [`None`]. |
| fn clone_request(&self, req: &Req) -> Option<Req>; |
| } |