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 Policy for Attempts { /// type Future = future::Ready; /// /// fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option { /// 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 { /// Some(req.clone()) /// } /// } /// ``` pub trait Policy: Sized { /// The [`Future`] type returned by [`Policy::retry`]. type Future: Future; /// 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; /// 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; }