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