tower-fallback: switch to Box<dyn Error + Send + Sync + 'static>
Previously the code used Either for error handling, but a boxed std Error is smaller in the happy path and more useful.
This commit is contained in:
parent
4be0a8edc3
commit
ecda5445d5
|
@ -36,7 +36,7 @@ dependencies = [
|
|||
"ident_case",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
|
@ -51,9 +51,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccc9a9dd069569f212bc4330af9f17c4afb5e8ce185e83dbb14f1349dda18b10"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
|
@ -426,7 +426,7 @@ dependencies = [
|
|||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"strsim 0.9.3",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -437,7 +437,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
|
|||
dependencies = [
|
||||
"darling_core",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -455,7 +455,7 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||
dependencies = [
|
||||
"generic-array 0.14.2",
|
||||
"generic-array 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -466,7 +466,7 @@ checksum = "e6269d127174b18c665e683e23c2c55d3735fadbec4181c7c70b0450b764bfa5"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -489,12 +489,6 @@ dependencies = [
|
|||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
||||
|
||||
[[package]]
|
||||
name = "equihash"
|
||||
version = "0.1.0"
|
||||
|
@ -616,7 +610,7 @@ dependencies = [
|
|||
"proc-macro-hack",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -683,9 +677,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.2"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac746a5f3bbfdadd6106868134545e684693d54d9d44f6e9588a7d54af0bf980"
|
||||
checksum = "60fb4bb6bba52f78a471264d9a3b7d026cc0af47b22cd2cffbc0b787ca003e63"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
|
@ -725,14 +719,14 @@ checksum = "90454ce4de40b7ca6a8968b5ef367bdab48413962588d0d2b1638d60090c35d7"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff"
|
||||
checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
|
@ -741,10 +735,10 @@ dependencies = [
|
|||
"futures-util",
|
||||
"http",
|
||||
"indexmap",
|
||||
"log",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util 0.3.1",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1283,7 +1277,7 @@ checksum = "6a0ffd45cf79d88737d7cc85bfd5d2894bee1139b356e616fe85dc389c61aaf7"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1313,7 +1307,7 @@ dependencies = [
|
|||
"proc-macro-error-attr",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
@ -1325,7 +1319,7 @@ checksum = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
"syn-mid",
|
||||
"version_check",
|
||||
]
|
||||
|
@ -1529,9 +1523,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.56"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
|
@ -1701,7 +1695,7 @@ checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1847,7 +1841,7 @@ checksum = "5254766110c377a921c002ca0775d4e384ba69af951fc4329d9dd77af2c25763"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1883,7 +1877,7 @@ dependencies = [
|
|||
"proc-macro-error",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1905,9 +1899,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.33"
|
||||
version = "1.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd"
|
||||
checksum = "936cae2873c940d92e697597c5eee105fb570cd5689c695806f672883653349b"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
|
@ -1922,7 +1916,7 @@ checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1933,7 +1927,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
|
@ -1996,7 +1990,7 @@ checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2050,7 +2044,7 @@ checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2154,7 +2148,6 @@ dependencies = [
|
|||
name = "tower-fallback"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"either",
|
||||
"futures-core",
|
||||
"pin-project",
|
||||
"tokio",
|
||||
|
@ -2272,7 +2265,7 @@ checksum = "f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2347,9 +2340,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
|
||||
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
|
@ -2678,6 +2671,6 @@ checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.33",
|
||||
"syn 1.0.34",
|
||||
"synstructure",
|
||||
]
|
||||
|
|
|
@ -6,7 +6,6 @@ license = "MIT"
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
either = "1.5"
|
||||
tower = "0.3"
|
||||
futures-core = "0.3.5"
|
||||
pin-project = "0.4.20"
|
||||
|
|
|
@ -7,11 +7,12 @@ use std::{
|
|||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use either::Either;
|
||||
use futures_core::ready;
|
||||
use pin_project::pin_project;
|
||||
use tower::Service;
|
||||
|
||||
use crate::BoxedError;
|
||||
|
||||
/// Future that completes either with the first service's successful response, or
|
||||
/// with the second service's response.
|
||||
#[pin_project]
|
||||
|
@ -19,6 +20,7 @@ pub struct ResponseFuture<S1, S2, Request>
|
|||
where
|
||||
S1: Service<Request>,
|
||||
S2: Service<Request, Response = <S1 as Service<Request>>::Response>,
|
||||
S2::Error: Into<BoxedError>,
|
||||
{
|
||||
#[pin]
|
||||
state: ResponseState<S1, S2, Request>,
|
||||
|
@ -29,6 +31,7 @@ enum ResponseState<S1, S2, Request>
|
|||
where
|
||||
S1: Service<Request>,
|
||||
S2: Service<Request>,
|
||||
S2::Error: Into<BoxedError>,
|
||||
{
|
||||
PollResponse1 {
|
||||
#[pin]
|
||||
|
@ -52,6 +55,7 @@ impl<S1, S2, Request> ResponseFuture<S1, S2, Request>
|
|||
where
|
||||
S1: Service<Request>,
|
||||
S2: Service<Request, Response = <S1 as Service<Request>>::Response>,
|
||||
S2::Error: Into<BoxedError>,
|
||||
{
|
||||
pub(crate) fn new(fut: S1::Future, req: Request, svc2: S2) -> Self {
|
||||
ResponseFuture {
|
||||
|
@ -64,11 +68,9 @@ impl<S1, S2, Request> Future for ResponseFuture<S1, S2, Request>
|
|||
where
|
||||
S1: Service<Request>,
|
||||
S2: Service<Request, Response = <S1 as Service<Request>>::Response>,
|
||||
S2::Error: Into<BoxedError>,
|
||||
{
|
||||
type Output = Result<
|
||||
<S1 as Service<Request>>::Response,
|
||||
Either<<S1 as Service<Request>>::Error, <S2 as Service<Request>>::Error>,
|
||||
>;
|
||||
type Output = Result<<S1 as Service<Request>>::Response, BoxedError>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.project();
|
||||
|
@ -88,7 +90,7 @@ where
|
|||
}
|
||||
},
|
||||
ResponseStateProj::PollReady2 { svc2, .. } => match ready!(svc2.poll_ready(cx)) {
|
||||
Err(e) => return Poll::Ready(Err(Either::Right(e))),
|
||||
Err(e) => return Poll::Ready(Err(e.into())),
|
||||
Ok(()) => {
|
||||
if let __ResponseStateProjectionOwned::PollReady2 { mut svc2, req } =
|
||||
this.state.as_mut().project_replace(ResponseState::Tmp)
|
||||
|
@ -102,7 +104,7 @@ where
|
|||
}
|
||||
},
|
||||
ResponseStateProj::PollResponse2 { fut } => {
|
||||
return fut.poll(cx).map_err(Either::Right)
|
||||
return fut.poll(cx).map_err(Into::into)
|
||||
}
|
||||
ResponseStateProj::Tmp => unreachable!(),
|
||||
}
|
||||
|
@ -118,6 +120,7 @@ where
|
|||
S1::Future: Debug,
|
||||
S2: Debug,
|
||||
S2::Future: Debug,
|
||||
S2::Error: Into<BoxedError>,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("ResponseFuture")
|
||||
|
@ -134,6 +137,7 @@ where
|
|||
S1::Future: Debug,
|
||||
S2: Debug,
|
||||
S2::Future: Debug,
|
||||
S2::Error: Into<BoxedError>,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
|
|
|
@ -6,4 +6,5 @@ pub mod future;
|
|||
mod service;
|
||||
|
||||
pub use self::service::Fallback;
|
||||
pub use either::Either;
|
||||
|
||||
pub type BoxedError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use super::future::ResponseFuture;
|
||||
|
||||
use either::Either;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use tower::Service;
|
||||
|
||||
use super::future::ResponseFuture;
|
||||
use crate::BoxedError;
|
||||
|
||||
/// Provides fallback processing on a second service if the first service returned an error.
|
||||
#[derive(Debug)]
|
||||
pub struct Fallback<S1, S2>
|
||||
|
@ -36,15 +37,17 @@ impl<S1, S2, Request> Service<Request> for Fallback<S1, S2>
|
|||
where
|
||||
S1: Service<Request>,
|
||||
S2: Service<Request, Response = <S1 as Service<Request>>::Response>,
|
||||
S1::Error: Into<BoxedError>,
|
||||
S2::Error: Into<BoxedError>,
|
||||
S2: Clone,
|
||||
Request: Clone,
|
||||
{
|
||||
type Response = <S1 as Service<Request>>::Response;
|
||||
type Error = Either<<S1 as Service<Request>>::Error, <S2 as Service<Request>>::Error>;
|
||||
type Error = BoxedError;
|
||||
type Future = ResponseFuture<S1, S2, Request>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.svc1.poll_ready(cx).map_err(Either::Left)
|
||||
self.svc1.poll_ready(cx).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn call(&mut self, request: Request) -> Self::Future {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use tower::{service_fn, Service, ServiceExt};
|
||||
use tower_fallback::{Either, Fallback};
|
||||
use tower_fallback::Fallback;
|
||||
|
||||
#[tokio::test]
|
||||
async fn fallback() {
|
||||
|
@ -24,10 +24,7 @@ async fn fallback() {
|
|||
|
||||
let mut svc = Fallback::new(svc1, svc2);
|
||||
|
||||
assert_eq!(svc.ready_and().await.unwrap().call(1).await, Ok(1));
|
||||
assert_eq!(svc.ready_and().await.unwrap().call(11).await, Ok(111));
|
||||
assert_eq!(
|
||||
svc.ready_and().await.unwrap().call(21).await,
|
||||
Err(Either::Right("too big value on svc2"))
|
||||
);
|
||||
assert_eq!(svc.ready_and().await.unwrap().call(1).await.unwrap(), 1);
|
||||
assert_eq!(svc.ready_and().await.unwrap().call(11).await.unwrap(), 111);
|
||||
assert!(svc.ready_and().await.unwrap().call(21).await.is_err());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue