| 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>; | |
| } |