timeout: update to Box<dyn Error> (#170)

This commit is contained in:
Sean McArthur 2019-02-27 10:35:25 -08:00 committed by Carl Lerche
parent d874c251ff
commit 79a98ea05d
1 changed files with 29 additions and 124 deletions

View File

@ -12,11 +12,14 @@ extern crate tokio_timer;
extern crate tower_service;
use futures::{Async, Future, Poll};
use tokio_timer::{clock, Delay, Error as TimerError};
use tokio_timer::{clock, Delay};
use tower_service::Service;
use std::time::Duration;
use std::{error, fmt};
use self::error::Elapsed;
type Error = Box<::std::error::Error + Send + Sync>;
/// Applies a timeout to requests.
#[derive(Debug, Clone)]
@ -25,23 +28,6 @@ pub struct Timeout<T> {
timeout: Duration,
}
/// Errors produced by `Timeout`.
#[derive(Debug)]
pub struct Error<T>(Kind<T>);
/// Timeout error variants
#[derive(Debug)]
enum Kind<T> {
/// Inner value returned an error
Inner(T),
/// The timeout elapsed.
Elapsed,
/// Timer returned an error.
Timer(TimerError),
}
/// `Timeout` response future
#[derive(Debug)]
pub struct ResponseFuture<T> {
@ -61,13 +47,14 @@ impl<T> Timeout<T> {
impl<S, Request> Service<Request> for Timeout<S>
where
S: Service<Request>,
S::Error: Into<Error>,
{
type Response = S::Response;
type Error = Error<S::Error>;
type Error = Error;
type Future = ResponseFuture<S::Future>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.inner.poll_ready().map_err(|e| Error(Kind::Inner(e)))
self.inner.poll_ready().map_err(Into::into)
}
fn call(&mut self, request: Request) -> Self::Future {
@ -83,123 +70,41 @@ where
impl<T> Future for ResponseFuture<T>
where
T: Future,
T::Error: Into<Error>,
{
type Item = T::Item;
type Error = Error<T::Error>;
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
// First, try polling the future
match self.response.poll() {
Ok(Async::Ready(v)) => return Ok(Async::Ready(v)),
Ok(Async::NotReady) => {}
Err(e) => return Err(Error(Kind::Inner(e))),
match self.response.poll().map_err(Into::into)? {
Async::Ready(v) => return Ok(Async::Ready(v)),
Async::NotReady => {}
}
// Now check the sleep
match self.sleep.poll() {
Ok(Async::NotReady) => Ok(Async::NotReady),
Ok(Async::Ready(_)) => Err(Error(Kind::Elapsed)),
Err(e) => Err(Error(Kind::Timer(e))),
match self.sleep.poll()? {
Async::NotReady => Ok(Async::NotReady),
Async::Ready(_) => Err(Elapsed(()).into()),
}
}
}
// ===== impl Error =====
impl<T> fmt::Display for Error<T>
where
T: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
Kind::Inner(ref why) => fmt::Display::fmt(why, f),
Kind::Elapsed => f.pad("request timed out"),
Kind::Timer(ref why) => fmt::Display::fmt(why, f),
}
}
}
impl<T> error::Error for Error<T>
where
T: error::Error + 'static,
{
fn description(&self) -> &str {
match self.0 {
Kind::Inner(ref e) => e.description(),
Kind::Elapsed => "request timed out",
Kind::Timer(ref e) => e.description(),
}
}
fn source(&self) -> Option<&(error::Error + 'static)> {
let kind = &self.0;
if let Kind::Inner(ref why) = kind {
Some(why)
} else {
None
}
}
}
// ===== impl Error =====
impl<T> Error<T> {
/// Create a new `Error` representing the inner value completing with `Err`.
pub fn inner(err: T) -> Error<T> {
Error(Kind::Inner(err))
}
/// Returns `true` if the error was caused by the inner value completing
/// with `Err`.
pub fn is_inner(&self) -> bool {
match self.0 {
Kind::Inner(_) => true,
_ => false,
}
}
/// Consumes `self`, returning the inner future error.
pub fn into_inner(self) -> Option<T> {
match self.0 {
Kind::Inner(err) => Some(err),
_ => None,
}
}
/// Create a new `Error` representing the inner value not completing before
/// the deadline is reached.
pub fn elapsed() -> Error<T> {
Error(Kind::Elapsed)
}
/// Returns `true` if the error was caused by the inner value not completing
/// before the deadline is reached.
pub fn is_elapsed(&self) -> bool {
match self.0 {
Kind::Elapsed => true,
_ => false,
}
}
/// Creates a new `Error` representing an error encountered by the timer
/// implementation
pub fn timer(err: TimerError) -> Error<T> {
Error(Kind::Timer(err))
}
/// Returns `true` if the error was caused by the timer.
pub fn is_timer(&self) -> bool {
match self.0 {
Kind::Timer(_) => true,
_ => false,
}
}
/// Consumes `self`, returning the error raised by the timer implementation.
pub fn into_timer(self) -> Option<TimerError> {
match self.0 {
Kind::Timer(err) => Some(err),
_ => None,
/// Timeout error types
pub mod error {
use std::{error::Error, fmt};
/// The timeout elapsed.
#[derive(Debug)]
pub struct Elapsed(pub(super) ());
impl fmt::Display for Elapsed {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("request timed out")
}
}
impl Error for Elapsed {}
}