Use `tokio::timer` instead of `tokio_timer`; use Kind pattern (#141)

This commit is contained in:
David Barsky 2019-01-15 15:05:14 -05:00 committed by GitHub
parent 5db8510892
commit 68d3f6c22e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 98 additions and 20 deletions

View File

@ -3,13 +3,17 @@
//! If the response does not complete within the specified timeout, the response //! If the response does not complete within the specified timeout, the response
//! will be aborted. //! will be aborted.
#![doc(html_root_url = "https://docs.rs/tower-timeout/0.1.0")]
#![deny(missing_debug_implementations, missing_docs)]
#![cfg_attr(test, deny(warnings))]
extern crate futures; extern crate futures;
extern crate tower_service; extern crate tower_service;
extern crate tokio_timer; extern crate tokio_timer;
use futures::{Future, Poll, Async}; use futures::{Future, Poll, Async};
use tower_service::Service; use tower_service::Service;
use tokio_timer::{clock, Delay}; use tokio_timer::{clock, Delay, Error as TimerError};
use std::{error, fmt}; use std::{error, fmt};
use std::time::Duration; use std::time::Duration;
@ -23,12 +27,19 @@ pub struct Timeout<T> {
/// Errors produced by `Timeout`. /// Errors produced by `Timeout`.
#[derive(Debug)] #[derive(Debug)]
pub enum Error<T> { pub struct Error<T>(Kind<T>);
/// The inner service produced an error
/// Timeout error variants
#[derive(Debug)]
enum Kind<T> {
/// Inner value returned an error
Inner(T), Inner(T),
/// The request did not complete within the specified timeout. /// The timeout elapsed.
Timeout, Elapsed,
/// Timer returned an error.
Timer(TimerError),
} }
/// `Timeout` response future /// `Timeout` response future
@ -41,6 +52,7 @@ pub struct ResponseFuture<T> {
// ===== impl Timeout ===== // ===== impl Timeout =====
impl<T> Timeout<T> { impl<T> Timeout<T> {
/// Creates a new Timeout
pub fn new(inner: T, timeout: Duration) -> Self { pub fn new(inner: T, timeout: Duration) -> Self {
Timeout { Timeout {
inner, inner,
@ -59,7 +71,9 @@ where
fn poll_ready(&mut self) -> Poll<(), Self::Error> { fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.inner.poll_ready() self.inner.poll_ready()
.map_err(Error::Inner) .map_err(|e| {
Error(Kind::Inner(e))
})
} }
fn call(&mut self, request: Request) -> Self::Future { fn call(&mut self, request: Request) -> Self::Future {
@ -83,19 +97,18 @@ where T: Future,
match self.response.poll() { match self.response.poll() {
Ok(Async::Ready(v)) => return Ok(Async::Ready(v)), Ok(Async::Ready(v)) => return Ok(Async::Ready(v)),
Ok(Async::NotReady) => {} Ok(Async::NotReady) => {}
Err(e) => return Err(Error::Inner(e)), Err(e) => return Err(Error(Kind::Inner(e))),
} }
// Now check the sleep // Now check the sleep
match self.sleep.poll() { match self.sleep.poll() {
Ok(Async::NotReady) => Ok(Async::NotReady), Ok(Async::NotReady) => Ok(Async::NotReady),
Ok(Async::Ready(_)) => Err(Error::Timeout), Ok(Async::Ready(_)) => Err(Error(Kind::Elapsed)),
Err(_) => Err(Error::Timeout), Err(e) => Err(Error(Kind::Timer(e))),
} }
} }
} }
// ===== impl Error ===== // ===== impl Error =====
impl<T> fmt::Display for Error<T> impl<T> fmt::Display for Error<T>
@ -103,30 +116,95 @@ where
T: fmt::Display, T: fmt::Display,
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match self.0 {
Error::Inner(ref why) => fmt::Display::fmt(why, f), Kind::Inner(ref why) => fmt::Display::fmt(why, f),
Error::Timeout => f.pad("request timed out"), Kind::Elapsed => f.pad("request timed out"),
Kind::Timer(ref why) => fmt::Display::fmt(why, f),
} }
} }
} }
impl<T> error::Error for Error<T> impl<T> error::Error for Error<T>
where where
T: error::Error, T: error::Error + 'static,
{ {
fn cause(&self) -> Option<&error::Error> { fn description(&self) -> &str {
if let Error::Inner(ref why) = *self { 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) Some(why)
} else { } else {
None None
} }
} }
}
fn description(&self) -> &str { // ===== impl Error =====
match *self {
Error::Inner(_) => "inner service error", impl<T> Error<T> {
Error::Timeout => "request timed out", /// 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,
}
}
} }