2017-10-03 10:03:14 -07:00
|
|
|
[workspace]
|
|
|
|
|
|
|
|
members = [
|
2017-10-05 13:41:44 -07:00
|
|
|
"tower-balance",
|
2017-10-10 10:38:40 -07:00
|
|
|
"tower-buffer",
|
Add the DirectService trait (#118)
This patch adds the `DirectService` trait, and related implementations
over it in `tower_balance` and `tower_buffer`. `DirectService` is
similar to a `Service`, but must be "driven" through calls to
`poll_service` for the futures returned by `call` to make progress.
The motivation behind adding this trait is that many current `Service`
implementations spawn long-running futures when the service is created,
which then drive the work necessary to turn requests into responses. A
simple example of this is a service that writes requests over a
`TcpStream` and reads responses over that same `TcpStream`. The
underlying stream must be read from to discover new responses, but there
is no single entity to drive that task. The returned futures would share
access to the stream (and worse yet, may get responses out of order),
and then service itself is not guaranteed to see any more calls to it as
the client is waiting for its requests to finish.
`DirectService` solves this by introducing a new method, `poll_service`,
which must be called to make progress on in-progress futures.
Furthermore, like `Future::poll`, `poll_service` must be called whenever
the associated task is notified so that the service can also respect
time-based operations like heartbeats.
The PR includes changes to both `tower_balance::Balance` and
`tower_buffer::Buffer` to add support for wrapping `DirectService`s. For
`Balance` this is straightforward: if the inner service is a `Service`,
the `Balance` also implements `Service`; if the inner service is a
`DirectService`, the `Balance` is itself also a `DirectService`. For
`Buffer`, this is more involved, as a `Buffer` turns any `DirectService`
*into* a `Service`. The `Buffer`'s `Worker` is spawned, and will
therefore drive the wrapped `DirectService`.
One complication arises in that `Buffer<T>` requires that `T: Service`,
but you can safely construct a `Buffer` over a `DirectService` per the
above. `Buffer` works around this by exposing
```rust
impl Service for HandleTo<S> where S: DirectService {}
```
And giving out `Buffer<HandleTo<S>>` when the `new_directed(s: S)`
constructor is invoked. Since `Buffer` never calls any methods on the
service it wraps, `HandleTo`'s implementation just consists of calls to
`unreachable!()`.
Note that `tower_buffer` now also includes a `DirectedService` type,
which is a wrapper around a `Service` that implements `DirectService`.
In theory, we could do away with this by adding a blanket impl:
```rust
impl<T> DirectedService for T where T: Service {}
```
but until we have specialization, this would prevent downstream users
from implementing `DirectService` themselves.
Finally, this also makes `Buffer` use a bounded mpsc channel, which
introduces a new capacity argument to `Buffer::new`.
Fixes #110.
2018-11-19 09:30:46 -08:00
|
|
|
"tower-direct-service",
|
2017-10-05 13:41:44 -07:00
|
|
|
"tower-discover",
|
2017-10-03 10:03:14 -07:00
|
|
|
"tower-filter",
|
2018-02-20 11:04:03 -08:00
|
|
|
"tower-in-flight-limit",
|
2017-10-03 10:03:14 -07:00
|
|
|
"tower-mock",
|
|
|
|
"tower-rate-limit",
|
2017-10-05 13:41:44 -07:00
|
|
|
"tower-reconnect",
|
2018-08-28 11:05:15 -07:00
|
|
|
"tower-retry",
|
2017-11-02 12:26:32 -07:00
|
|
|
"tower-router",
|
2018-04-25 12:35:52 -07:00
|
|
|
"tower-service",
|
2017-10-03 10:03:14 -07:00
|
|
|
"tower-timeout",
|
2017-10-21 14:06:39 -07:00
|
|
|
"tower-util",
|
2018-07-11 15:03:20 -07:00
|
|
|
"tower-watch",
|
2017-10-03 10:03:14 -07:00
|
|
|
]
|
|
|
|
|
2017-09-27 10:40:02 -07:00
|
|
|
[dev-dependencies]
|
2018-04-25 12:35:52 -07:00
|
|
|
futures = "0.1"
|
2018-02-23 20:24:22 -08:00
|
|
|
log = "0.4.1"
|
|
|
|
env_logger = { version = "0.5.3", default-features = false }
|
2017-09-27 10:40:02 -07:00
|
|
|
tokio-timer = "0.1"
|
|
|
|
futures-cpupool = "0.1"
|