Repository: tower-rs/tower
Pull request #373 (2019-12-01 21:55:57)

Update timeout, tower-test and reconnect
`tower-test` needs a better refactor to follow what we do in `tokio/tests`.

jonhoo: I wonder if `tower` should also go the route of `tokio` and bundle all these subcrates into one crate with features?
LucioFranco: I am gonna merge this so follow up work can happen.

Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 20cce10..3f3d775 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,12 +12,12 @@ members = [
   # "tower-load",
   # "tower-load-shed",
   # "tower-ready-cache",
-  # "tower-reconnect",
+  "tower-reconnect",
   # "tower-retry",
   "tower-service",
   # "tower-spawn-ready",
-  # "tower-test",
-  # "tower-timeout",
+  "tower-test",
+  "tower-timeout",
   "tower-make",
   # "tower-util",
 ]
diff --git a/tower-reconnect/CHANGELOG.md b/tower-reconnect/CHANGELOG.md
index 19df3db..e927679 100644
--- a/tower-reconnect/CHANGELOG.md
+++ b/tower-reconnect/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.3.0 (December 1, 2019)
+
+- Update to `tower-service 0.3`
+
 # 0.3.0-alpha.2 (September 30, 2019)
 
 - Move to `futures-*-preview 0.3.0-alpha.19`
diff --git a/tower-reconnect/Cargo.toml b/tower-reconnect/Cargo.toml
index 21610cf..4ff95d1 100644
--- a/tower-reconnect/Cargo.toml
+++ b/tower-reconnect/Cargo.toml
@@ -8,7 +8,7 @@ name = "tower-reconnect"
 #   - README.md
 # - Update CHANGELOG.md.
 # - Create "v0.1.x" git tag.
-version = "0.3.0-alpha.2"
+version = "0.3.0"
 authors = ["Tower Maintainers <team@tower-rs.com>"]
 license = "MIT"
 readme = "README.md"
@@ -23,6 +23,6 @@ edition = "2018"
 
 [dependencies]
 log = "0.4.1"
-tower-service = { version = "=0.3.0-alpha.2", path = "../tower-service" }
-tower-make = { version = "=0.3.0-alpha.2a", path = "../tower-make" }
+tower-service = { version = "0.3", path = "../tower-service" }
+tower-make = { version = "0.3", path = "../tower-make" }
 pin-project = "0.4"
diff --git a/tower-reconnect/src/future.rs b/tower-reconnect/src/future.rs
index 7640b08..e12a795 100644
--- a/tower-reconnect/src/future.rs
+++ b/tower-reconnect/src/future.rs
@@ -6,6 +6,7 @@ use std::{
     task::{Context, Poll},
 };
 
+/// Future that resolves to the response or failure to connect.
 #[pin_project]
 #[derive(Debug)]
 pub struct ResponseFuture<F> {
diff --git a/tower-reconnect/src/lib.rs b/tower-reconnect/src/lib.rs
index 3cea6d1..ede8f5e 100644
--- a/tower-reconnect/src/lib.rs
+++ b/tower-reconnect/src/lib.rs
@@ -1,4 +1,4 @@
-#![doc(html_root_url = "https://docs.rs/tower-reconnect/0.3.0-alpha.2")]
+#![doc(html_root_url = "https://docs.rs/tower-reconnect/0.3.0")]
 #![warn(missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
 #![allow(missing_docs)] // TODO
 #![allow(elided_lifetimes_in_paths)]
@@ -16,6 +16,7 @@ use std::{
 use tower_make::MakeService;
 use tower_service::Service;
 
+/// Reconnect to failed services.
 pub struct Reconnect<M, Target>
 where
     M: Service<Target>,
@@ -38,6 +39,7 @@ impl<M, Target> Reconnect<M, Target>
 where
     M: Service<Target>,
 {
+    /// Lazily connect and reconnect to a Service.
     pub fn new<S, Request>(mk_service: M, target: Target) -> Self
     where
         M: Service<Target, Response = S>,
@@ -51,6 +53,15 @@ where
             target,
         }
     }
+
+    /// Reconnect to a already connected Service.
+    pub fn with_connection(init_conn: M::Response, mk_service: M, target: Target) -> Self {
+        Reconnect {
+            mk_service,
+            state: State::Connected(init_conn),
+            target,
+        }
+    }
 }
 
 impl<M, Target, S, Request> Service<Request> for Reconnect<M, Target>
diff --git a/tower-timeout/CHANGELOG.md b/tower-timeout/CHANGELOG.md
index 1605716..6d06991 100644
--- a/tower-timeout/CHANGELOG.md
+++ b/tower-timeout/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.3.0 (December 1, 2019)
+
+- Update to `tower-service 0.3`
+
 # 0.3.0-alpha.2 (September 30, 2019)
 
 - Move to `futures-*-preview 0.3.0-alpha.19`
diff --git a/tower-timeout/Cargo.toml b/tower-timeout/Cargo.toml
index da81afa..58b90a3 100644
--- a/tower-timeout/Cargo.toml
+++ b/tower-timeout/Cargo.toml
@@ -7,14 +7,14 @@ name = "tower-timeout"
 #   - Cargo.toml
 #   - README.md
 # - Update CHANGELOG.md.
-# - Create "v0.1.x" git tag.
-version = "0.3.0-alpha.2"
+# - Create "v0.3.x" git tag.
+version = "0.3.0"
 authors = ["Tower Maintainers <team@tower-rs.com>"]
 license = "MIT"
 readme = "README.md"
 repository = "https://github.com/tower-rs/tower"
 homepage = "https://github.com/tower-rs/tower"
-documentation = "https://docs.rs/tower-timeout/0.3.0-alpha.2"
+documentation = "https://docs.rs/tower-timeout/0.3.0"
 description = """
 Apply a timeout to requests, ensuring completion within a fixed time duration.
 """
@@ -22,7 +22,7 @@ categories = ["asynchronous", "network-programming"]
 edition = "2018"
 
 [dependencies]
-tower-service = { version = "=0.3.0-alpha.2", path = "../tower-service" }
-tower-layer = { version = "=0.3.0-alpha.2", path = "../tower-layer" }
-tokio-timer = "=0.3.0-alpha.6"
+tower-service = { version = "0.3", path = "../tower-service" }
+tower-layer = { version = "0.3", path = "../tower-layer" }
+tokio = { version = "0.2", features = ["time"] }
 pin-project = "0.4"
diff --git a/tower-timeout/src/future.rs b/tower-timeout/src/future.rs
index 77d066d..db14a76 100644
--- a/tower-timeout/src/future.rs
+++ b/tower-timeout/src/future.rs
@@ -7,7 +7,7 @@ use std::{
     pin::Pin,
     task::{Context, Poll},
 };
-use tokio_timer::Delay;
+use tokio::time::Delay;
 
 /// `Timeout` response future
 #[pin_project]
diff --git a/tower-timeout/src/lib.rs b/tower-timeout/src/lib.rs
index cef234d..73bad03 100644
--- a/tower-timeout/src/lib.rs
+++ b/tower-timeout/src/lib.rs
@@ -1,4 +1,4 @@
-#![doc(html_root_url = "https://docs.rs/tower-timeout/0.3.0-alpha.2")]
+#![doc(html_root_url = "https://docs.rs/tower-timeout/0.3.0")]
 #![warn(
     missing_debug_implementations,
     missing_docs,
@@ -19,11 +19,8 @@ pub use crate::layer::TimeoutLayer;
 
 use crate::{error::Error, future::ResponseFuture};
 use std::task::{Context, Poll};
-use tokio_timer::{clock, delay};
-
-use tower_service::Service;
-
 use std::time::Duration;
+use tower_service::Service;
 
 /// Applies a timeout to requests.
 #[derive(Debug, Clone)]
@@ -59,7 +56,7 @@ where
 
     fn call(&mut self, request: Request) -> Self::Future {
         let response = self.inner.call(request);
-        let sleep = delay(clock::now() + self.timeout);
+        let sleep = tokio::time::delay_for(self.timeout);
 
         ResponseFuture::new(response, sleep)
     }


Test patch:
diff --git a/tower-test/CHANGELOG.md b/tower-test/CHANGELOG.md
index 633a866..55ab0f4 100644
--- a/tower-test/CHANGELOG.md
+++ b/tower-test/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 0.3.0 (December 1, 2019)
+
+- Remove `futures-executor` dependency
+- Update to non-alpha versions
+- Add `mock::task_fn` util fn
+
 # 0.3.0-alpha.2 (September 30, 2019)
 
 - Move to `futures-*-preview 0.3.0-alpha.19`
diff --git a/tower-test/Cargo.toml b/tower-test/Cargo.toml
index e975fe9..7ce36ea 100644
--- a/tower-test/Cargo.toml
+++ b/tower-test/Cargo.toml
@@ -8,7 +8,7 @@ name = "tower-test"
 #   - README.md
 # - Update CHANGELOG.md.
 # - Create "v0.1.x" git tag.
-version = "0.3.0-alpha.2"
+version = "0.3.0"
 authors = ["Tower Maintainers <team@tower-rs.com>"]
 license = "MIT"
 readme = "README.md"
@@ -22,9 +22,8 @@ categories = ["asynchronous", "network-programming"]
 edition = "2018"
 
 [dependencies]
-futures-util-preview = "=0.3.0-alpha.19"
-futures-executor-preview = "=0.3.0-alpha.19"
-tokio-test = "=0.2.0-alpha.6"
-tokio-sync = "=0.2.0-alpha.6"
-tower-service = { version = "=0.3.0-alpha.2", path = "../tower-service" }
+futures-util = "0.3"
+tokio = { version = "0.2", features = ["sync"]}
+tokio-test = "0.2"
+tower-service = { version = "0.3", path = "../tower-service" }
 pin-project = "0.4"
diff --git a/tower-test/src/lib.rs b/tower-test/src/lib.rs
index 08931ad..e41f107 100644
--- a/tower-test/src/lib.rs
+++ b/tower-test/src/lib.rs
@@ -1,4 +1,4 @@
-#![doc(html_root_url = "https://docs.rs/tower-test/0.3.0-alpha.2")]
+#![doc(html_root_url = "https://docs.rs/tower-test/0.3.0")]
 #![warn(
     missing_debug_implementations,
     missing_docs,
diff --git a/tower-test/src/macros.rs b/tower-test/src/macros.rs
index 1533e4f..aaa4ef7 100644
--- a/tower-test/src/macros.rs
+++ b/tower-test/src/macros.rs
@@ -14,15 +14,11 @@
 /// use tower_service::Service;
 /// use tower_test::mock;
 /// use std::task::{Poll, Context};
-/// use tokio_test::{task, assert_ready};
+/// use tokio_test::assert_ready;
 /// use futures_util::pin_mut;
 ///
 /// # fn main() {
-/// task::mock(|cx|{
-///     let (mut mock, mut handle) = mock::pair();
-///     pin_mut!(mock);
-///     pin_mut!(handle);
-///
+/// mock::task_fn(|cx, mock, handle|{
 ///     assert_ready!(mock.poll_ready(cx));
 ///
 ///     let _response = mock.call("hello");
diff --git a/tower-test/src/mock/future.rs b/tower-test/src/mock/future.rs
index 358c75a..872df02 100644
--- a/tower-test/src/mock/future.rs
+++ b/tower-test/src/mock/future.rs
@@ -3,7 +3,7 @@
 use crate::mock::error::{self, Error};
 use futures_util::ready;
 use pin_project::pin_project;
-use tokio_sync::oneshot;
+use tokio::sync::oneshot;
 
 use std::{
     future::Future,
diff --git a/tower-test/src/mock/mod.rs b/tower-test/src/mock/mod.rs
index cffe11d..7576d3c 100644
--- a/tower-test/src/mock/mod.rs
+++ b/tower-test/src/mock/mod.rs
@@ -6,7 +6,7 @@ pub mod future;
 use crate::mock::{error::Error, future::ResponseFuture};
 use core::task::Waker;
 
-use tokio_sync::{mpsc, oneshot};
+use tokio::sync::{mpsc, oneshot};
 use tower_service::Service;
 
 use std::{
@@ -18,6 +18,21 @@ use std::{
     u64,
 };
 
+/// Mock a task and Service.
+pub fn task_fn<T, U, F>(mut f: F)
+where
+    F: FnMut(&mut Context, &mut Pin<&mut Mock<T, U>>, &mut Pin<&mut Handle<T, U>>),
+{
+    tokio_test::task::spawn(()).enter(|cx, _| {
+        let (mock, handle) = pair();
+
+        futures_util::pin_mut!(mock);
+        futures_util::pin_mut!(handle);
+
+        f(cx, &mut mock, &mut handle)
+    })
+}
+
 /// A mock service
 #[derive(Debug)]
 pub struct Mock<T, U> {
@@ -142,7 +157,7 @@ impl<T, U> Service<T> for Mock<T, U> {
         let (tx, rx) = oneshot::channel();
         let send_response = SendResponse { tx };
 
-        match self.tx.lock().unwrap().try_send((request, send_response)) {
+        match self.tx.lock().unwrap().send((request, send_response)) {
             Ok(_) => {}
             Err(_) => {
                 // TODO: Can this be reached
@@ -208,8 +223,8 @@ impl<T, U> Handle<T, U> {
     ///
     /// This function blocks the current thread until a request is received.
     pub fn next_request(mut self: Pin<&mut Self>) -> Option<Request<T, U>> {
-        use futures_executor::block_on;
         use futures_util::future::poll_fn;
+        use tokio_test::block_on;
 
         block_on(poll_fn(|cx| self.as_mut().poll_request(cx)))
     }
diff --git a/tower-test/tests/mock.rs b/tower-test/tests/mock.rs
index 3221b2d..62b7868 100644
--- a/tower-test/tests/mock.rs
+++ b/tower-test/tests/mock.rs
@@ -1,17 +1,12 @@
-use futures_executor::block_on;
 use futures_util::pin_mut;
 use std::future::Future;
-use tokio_test::{assert_pending, assert_ready, task};
+use tokio_test::{assert_pending, assert_ready};
 use tower_service::Service;
 use tower_test::{assert_request_eq, mock};
 
 #[test]
 fn single_request_ready() {
-    task::mock(|cx| {
-        let (mock, handle) = new_mock();
-        pin_mut!(mock);
-        pin_mut!(handle);
-
+    mock::task_fn::<String, String, _>(|cx, mock, handle| {
         // No pending requests
         assert!(handle.as_mut().poll_request(cx).is_pending());
 
@@ -30,16 +25,14 @@ fn single_request_ready() {
         // Send the response
         send_response.send_response("yes?".into());
 
-        assert_eq!(block_on(response).unwrap().as_str(), "yes?");
+        assert_eq!(tokio_test::block_on(response).unwrap().as_str(), "yes?");
     });
 }
 
 #[test]
 #[should_panic]
 fn backpressure() {
-    task::mock(|cx| {
-        let (mut mock, mut handle) = new_mock();
-
+    mock::task_fn::<String, String, _>(|cx, mock, handle| {
         handle.allow(0);
 
         // Make sure the mock cannot accept more requests
@@ -49,10 +42,3 @@ fn backpressure() {
         mock.call("hello?".into());
     });
 }
-
-type Mock = mock::Mock<String, String>;
-type Handle = mock::Handle<String, String>;
-
-fn new_mock() -> (Mock, Handle) {
-    mock::pair()
-}