1 //! Middleware for retrying "failed" requests.
2 
3 pub mod budget;
4 pub mod future;
5 mod layer;
6 mod policy;
7 
8 pub use self::layer::RetryLayer;
9 pub use self::policy::Policy;
10 
11 use self::future::ResponseFuture;
12 use pin_project_lite::pin_project;
13 use std::task::{Context, Poll};
14 use tower_service::Service;
15 
16 pin_project! {
17     /// Configure retrying requests of "failed" responses.
18     ///
19     /// A [`Policy`] classifies what is a "failed" response.
20     #[derive(Clone, Debug)]
21     pub struct Retry<P, S> {
22         #[pin]
23         policy: P,
24         service: S,
25     }
26 }
27 
28 // ===== impl Retry =====
29 
30 impl<P, S> Retry<P, S> {
31     /// Retry the inner service depending on this [`Policy`].
new(policy: P, service: S) -> Self32     pub fn new(policy: P, service: S) -> Self {
33         Retry { policy, service }
34     }
35 
36     /// Get a reference to the inner service
get_ref(&self) -> &S37     pub fn get_ref(&self) -> &S {
38         &self.service
39     }
40 
41     /// Get a mutable reference to the inner service
get_mut(&mut self) -> &mut S42     pub fn get_mut(&mut self) -> &mut S {
43         &mut self.service
44     }
45 
46     /// Consume `self`, returning the inner service
into_inner(self) -> S47     pub fn into_inner(self) -> S {
48         self.service
49     }
50 }
51 
52 impl<P, S, Request> Service<Request> for Retry<P, S>
53 where
54     P: Policy<Request, S::Response, S::Error> + Clone,
55     S: Service<Request> + Clone,
56 {
57     type Response = S::Response;
58     type Error = S::Error;
59     type Future = ResponseFuture<P, S, Request>;
60 
poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>61     fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
62         // NOTE: the Future::poll impl for ResponseFuture assumes that Retry::poll_ready is
63         // equivalent to Ready.service.poll_ready. If this ever changes, that code must be updated
64         // as well.
65         self.service.poll_ready(cx)
66     }
67 
call(&mut self, request: Request) -> Self::Future68     fn call(&mut self, request: Request) -> Self::Future {
69         let cloned = self.policy.clone_request(&request);
70         let future = self.service.call(request);
71 
72         ResponseFuture::new(cloned, self.clone(), future)
73     }
74 }
75