tower_fallback/
service.rs1use std::task::{Context, Poll};
2
3use tower::Service;
4
5use super::future::ResponseFuture;
6use crate::BoxedError;
7
8pub trait FallbackPolicy<Response> {
10 fn should_fallback(&self, result: &Result<Response, BoxedError>) -> bool;
12}
13
14impl<Response, F> FallbackPolicy<Response> for F
15where
16 F: Fn(&Result<Response, BoxedError>) -> bool,
17{
18 fn should_fallback(&self, result: &Result<Response, BoxedError>) -> bool {
19 self(result)
20 }
21}
22
23#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
27pub struct OnError;
28
29impl<Response> FallbackPolicy<Response> for OnError {
30 fn should_fallback(&self, result: &Result<Response, BoxedError>) -> bool {
31 result.is_err()
32 }
33}
34
35#[derive(Debug)]
37pub struct Fallback<S1, S2, F = OnError>
38where
39 S2: Clone,
40{
41 svc1: S1,
42 svc2: S2,
43 policy: F,
44}
45
46impl<S1: Clone, S2: Clone, F: Clone> Clone for Fallback<S1, S2, F> {
47 fn clone(&self) -> Self {
48 Self {
49 svc1: self.svc1.clone(),
50 svc2: self.svc2.clone(),
51 policy: self.policy.clone(),
52 }
53 }
54}
55
56impl<S1, S2: Clone> Fallback<S1, S2, OnError> {
57 pub fn new(svc1: S1, svc2: S2) -> Self {
61 Self {
62 svc1,
63 svc2,
64 policy: OnError,
65 }
66 }
67}
68
69impl<S1, S2: Clone, F: Clone> Fallback<S1, S2, F> {
70 pub fn new_with_policy(svc1: S1, svc2: S2, policy: F) -> Self {
75 Self { svc1, svc2, policy }
76 }
77}
78
79impl<S1, S2, F, Request> Service<Request> for Fallback<S1, S2, F>
80where
81 S1: Service<Request>,
82 S2: Service<Request, Response = <S1 as Service<Request>>::Response>,
83 F: FallbackPolicy<<S1 as Service<Request>>::Response> + Clone,
84 S1::Error: Into<BoxedError>,
85 S2::Error: Into<BoxedError>,
86 S2: Clone,
87 Request: Clone,
88{
89 type Response = <S1 as Service<Request>>::Response;
90 type Error = BoxedError;
91 type Future = ResponseFuture<S1, S2, Request, F>;
92
93 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
94 self.svc1.poll_ready(cx).map_err(Into::into)
95 }
96
97 fn call(&mut self, request: Request) -> Self::Future {
98 let request2 = request.clone();
99 ResponseFuture::new(
100 self.svc1.call(request),
101 request2,
102 self.svc2.clone(),
103 self.policy.clone(),
104 )
105 }
106}