1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
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. 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>; }