change NewService to MakeService<Target, Request>

This commit is contained in:
Sean McArthur
2018-11-08 14:59:32 -08:00
parent b68120cc21
commit da0352cfc4
4 changed files with 113 additions and 113 deletions
+43 -28
View File
@@ -4,16 +4,17 @@ extern crate log;
extern crate tower_service;
use futures::{Future, Async, Poll};
use tower_service::{Service, NewService};
use tower_service::{Service, MakeService};
use std::{error, fmt};
pub struct Reconnect<T, Request>
pub struct Reconnect<T, Target, Request>
where
T: NewService<Request>,
T: MakeService<Target, Request>,
{
new_service: T,
state: State<T, Request>,
context: Target,
mk_service: T,
state: State<T::Future, T::Service>,
}
#[derive(Debug)]
@@ -23,47 +24,47 @@ pub enum Error<T, U> {
NotReady,
}
pub struct ResponseFuture<T, Request>
pub struct ResponseFuture<T, Target, Request>
where
// TODO:
// This struct should just be generic over the response future, but
// doing so would require changing the future's error type
T: NewService<Request>,
T: MakeService<Target, Request>,
{
inner: Option<<T::Service as Service<Request>>::Future>,
}
#[derive(Debug)]
enum State<T, Request>
where
T: NewService<Request>
{
enum State<F, S> {
Idle,
Connecting(T::Future),
Connected(T::Service),
Connecting(F),
Connected(S),
}
// ===== impl Reconnect =====
impl<T, Request> Reconnect<T, Request>
impl<T, Target, Request> Reconnect<T, Target, Request>
where
T: NewService<Request>,
T: MakeService<Target, Request>,
Target: Clone,
{
pub fn new(new_service: T) -> Self {
pub fn new(mk_service: T, context: Target) -> Self {
Reconnect {
new_service,
context,
mk_service,
state: State::Idle,
}
}
}
impl<T, Request> Service<Request> for Reconnect<T, Request>
impl<T, Target, Request> Service<Request> for Reconnect<T, Target, Request>
where
T: NewService<Request>
T: MakeService<Target, Request>,
Target: Clone,
{
type Response = T::Response;
type Error = Error<T::Error, T::InitError>;
type Future = ResponseFuture<T, Request>;
type Error = Error<T::Error, T::MakeError>;
type Future = ResponseFuture<T, Target, Request>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
use self::State::*;
@@ -75,7 +76,19 @@ where
match self.state {
Idle => {
trace!("poll_ready; idle");
let fut = self.new_service.new_service();
match self.mk_service.poll_ready() {
Ok(Async::Ready(())) => (),
Ok(Async::NotReady) => {
trace!("poll_ready; MakeService not ready");
return Ok(Async::NotReady);
}
Err(e) => {
trace!("poll_ready; MakeService error");
return Err(Error::Connect(e));
}
}
let fut = self.mk_service.make_service(self.context.clone());
self.state = Connecting(fut);
continue;
}
@@ -138,16 +151,18 @@ where
}
}
impl<T, Request> fmt::Debug for Reconnect<T, Request>
impl<T, Target, Request> fmt::Debug for Reconnect<T, Target, Request>
where
T: NewService<Request> + fmt::Debug,
T: MakeService<Target, Request> + fmt::Debug,
T::Future: fmt::Debug,
T::Service: fmt::Debug,
Target: fmt::Debug,
Request: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Reconnect")
.field("new_service", &self.new_service)
.field("context", &self.context)
.field("mk_service", &self.mk_service)
.field("state", &self.state)
.finish()
}
@@ -155,12 +170,12 @@ where
// ===== impl ResponseFuture =====
impl<T, Request> Future for ResponseFuture<T, Request>
impl<T, Target, Request> Future for ResponseFuture<T, Target, Request>
where
T: NewService<Request>,
T: MakeService<Target, Request>,
{
type Item = T::Response;
type Error = Error<T::Error, T::InitError>;
type Error = Error<T::Error, T::MakeError>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
trace!("poll response");
+50 -66
View File
@@ -9,17 +9,15 @@
//!
//! * [`Service`](trait.Service.html) is the primary trait and defines the request
//! / response exchange. See that trait for more details.
//! * [`NewService`](trait.NewService.html) is essentially a service factory. It
//! * [`MakeService`](trait.MakeService.html) is essentially a service factory. It
//! is responsible for generating `Service` values on demand.
#[macro_use]
extern crate futures;
use futures::{Future, IntoFuture, Poll};
use futures::{Future, Poll};
use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::Arc;
/// An asynchronous function from `Request` to a `Response`.
///
@@ -212,33 +210,6 @@ pub struct Ready<T, Request> {
_p: PhantomData<fn() -> Request>,
}
/// Creates new `Service` values.
///
/// Acts as a service factory. This is useful for cases where new `Service`
/// values must be produced. One case is a TCP servier listener. The listner
/// accepts new TCP streams, obtains a new `Service` value using the
/// `NewService` trait, and uses that new `Service` value to process inbound
/// requests on that new TCP stream.
pub trait NewService<Request> {
/// Responses given by the service
type Response;
/// Errors produced by the service
type Error;
/// The `Service` value created by this factory
type Service: Service<Request, Response = Self::Response, Error = Self::Error>;
/// Errors produced while building a service.
type InitError;
/// The future of the `Service` instance.
type Future: Future<Item = Self::Service, Error = Self::InitError>;
/// Create and return a new service value asynchronously.
fn new_service(&self) -> Self::Future;
}
impl<T, Request> Future for Ready<T, Request>
where T: Service<Request>,
{
@@ -257,49 +228,62 @@ where T: Service<Request>,
}
}
impl<F, R, E, S, Request> NewService<Request> for F
where F: Fn() -> R,
R: IntoFuture<Item = S, Error = E>,
/// Creates new `Service` values.
///
/// Acts as a service factory. This is useful for cases where new `Service`
/// values must be produced. One case is a TCP servier listener. The listner
/// accepts new TCP streams, obtains a new `Service` value using the
/// `MakeService` trait, and uses that new `Service` value to process inbound
/// requests on that new TCP stream.
///
/// This is essentially a trait alias for a `Service` of `Service`s.
pub trait MakeService<Target, Request> {
/// Responses given by the service
type Response;
/// Errors produced by the service
type Error;
/// The `Service` value created by this factory
type Service: Service<Request, Response = Self::Response, Error = Self::Error>;
/// Errors produced while building a service.
type MakeError;
/// The future of the `Service` instance.
type Future: Future<Item = Self::Service, Error = Self::MakeError>;
/// Returns `Ready` when the factory is able to process create more services.
///
/// If the service is at capacity, then `NotReady` is returned and the task
/// is notified when the service becomes ready again. This function is
/// expected to be called while on a task.
///
/// This is a **best effort** implementation. False positives are permitted.
/// It is permitted for the service to return `Ready` from a `poll_ready`
/// call and the next invocation of `call` results in an error.
fn poll_ready(&mut self) -> Poll<(), Self::MakeError>;
/// Create and return a new service value asynchronously.
fn make_service(&mut self, target: Target) -> Self::Future;
}
impl<M, S, Target, Request> MakeService<Target, Request> for M
where M: Service<Target, Response=S>,
S: Service<Request>,
{
type Response = S::Response;
type Error = S::Error;
type Service = S;
type InitError = E;
type Future = R::Future;
type MakeError = M::Error;
type Future = M::Future;
fn new_service(&self) -> Self::Future {
(*self)().into_future()
fn poll_ready(&mut self) -> Poll<(), Self::MakeError> {
Service::poll_ready(self)
}
}
impl<S, Request> NewService<Request> for Arc<S>
where
S: NewService<Request> + ?Sized,
{
type Response = S::Response;
type Error = S::Error;
type Service = S::Service;
type InitError = S::InitError;
type Future = S::Future;
fn new_service(&self) -> Self::Future {
(**self).new_service()
}
}
impl<S, Request> NewService<Request> for Rc<S>
where
S: NewService<Request> + ?Sized,
{
type Response = S::Response;
type Error = S::Error;
type Service = S::Service;
type InitError = S::InitError;
type Future = S::Future;
fn new_service(&self) -> Self::Future {
(**self).new_service()
fn make_service(&mut self, target: Target) -> Self::Future {
Service::call(self, target)
}
}
+1 -1
View File
@@ -14,4 +14,4 @@ pub use boxed::BoxService;
pub use either::EitherService;
pub use ext::ServiceExt;
pub use option::OptionService;
pub use service_fn::NewServiceFn;
pub use service_fn::ServiceFn;
+19 -18
View File
@@ -1,32 +1,33 @@
use futures::IntoFuture;
use tower_service::{Service, NewService};
use futures::{IntoFuture, Poll};
use tower_service::Service;
/// A `NewService` implemented by a closure.
pub struct NewServiceFn<T> {
/// A `Service` implemented by a closure.
pub struct ServiceFn<T> {
f: T,
}
// ===== impl NewServiceFn =====
// ===== impl ServiceFn =====
impl<T> NewServiceFn<T> {
impl<T> ServiceFn<T> {
/// Returns a new `NewServiceFn` with the given closure.
pub fn new(f: T) -> Self {
NewServiceFn { f }
ServiceFn { f }
}
}
impl<T, R, S, Request> NewService<Request> for NewServiceFn<T>
where T: Fn() -> R,
R: IntoFuture<Item = S>,
S: Service<Request>,
impl<T, F, Request> Service<Request> for ServiceFn<T>
where T: Fn(Request) -> F,
F: IntoFuture,
{
type Response = S::Response;
type Error = S::Error;
type Service = R::Item;
type InitError = R::Error;
type Future = R::Future;
type Response = F::Item;
type Error = F::Error;
type Future = F::Future;
fn new_service(&self) -> Self::Future {
(self.f)().into_future()
fn poll_ready(&mut self) -> Poll<(), F::Error> {
Ok(().into())
}
fn call(&mut self, req: Request) -> Self::Future {
(self.f)(req).into_future()
}
}