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