32 Commits

Author SHA1 Message Date
Carl Lerche
bec3937e87
buffer: switch to TypedExecutor (#205) 2019-03-25 10:56:12 -07:00
Carl Lerche
728f9d3c37
Fix fmt (#203) 2019-03-19 15:13:10 -07:00
Carl Lerche
733b597f38
Simplify Buffer::new error type
The returned error is now `Box<Error + Send + Sync>`.
2019-03-18 20:26:21 -07:00
Sean McArthur
20102a647b
buffer: fix panics if worker executor drops unexpectedly (#190) 2019-03-08 18:18:01 -08:00
Carl Lerche
bdcce9677b
depend on tower-service from crates.io (#186) 2019-03-06 13:38:58 -08:00
Carl Lerche
bf8c3b885a
mock: Use Box<Error> instead of a generic (#177)
Refs: #131
2019-03-01 13:56:57 -08:00
Lucio Franco
c5d70481bd
layer: Add tower-layer and the Layer trait (#163)
This change introduces the new `tower-layer` crate and the foundational `Layer` trait to go along with it. This trait allows one to easily compose a set of `Service`s that take an inner service. These services only modify the request/response. This also provides the `Layer` implementation for many of the tower crates.
2019-02-27 15:28:42 -05:00
Carl Lerche
8241fe8584
buffer: replace generic error with Box<Error> (#168)
Refs: #131
2019-02-26 13:40:16 -08:00
Carl Lerche
92653e68a6
Cleanup Buffer (#166)
* Move ResponseFuture, error types to dedicated mod
* Split code into multiple files.
* Remove `lazy_cell` dependency.
2019-02-25 10:01:26 -08:00
Carl Lerche
f42338934a
Require poll_ready to be called before call (#161)
This updates the `Service` contract requiring `poll_ready` to be called
before `call`. This allows `Service::call` to panic in the event the
user of the service omits `poll_ready` or does not wait until `Ready` is
observed.
2019-02-21 12:18:56 -08:00
Jon Gjengset
8390a1d288 Remove DirectService from tower-{balance,buffer} (#159) 2019-02-15 14:52:00 -08:00
David Barsky
d7e1b8f5dd Format tower with rustfmt; check in CI (#157) 2019-02-11 15:11:31 -08:00
Jon Gjengset
2d72bc8660 Switch tower-buffer to use tokio-sync (#152) 2019-01-28 11:23:03 -08:00
Jon Gjengset
d42f48bbbb
Expose Service errors through tower-buffer (#143)
In the past, any errors thrown by a `Service` wrapped in a
`tower_buffer::Buffer` were silently swallowed, and the handles were
simply informed that the connection to the `Service` was closed.

This patch captures errors from a wrapped `Service`, and communicates
that error to all pending and future requests. It does so by wrapping up
the error in an `Arc`, which is sent to all pending `oneshot` request
channels, and is stored in a shared location so that future requests
will see the error when their send to the `Worker` fail.

Note that this patch also removes the `open` field from `State`, as it
is no longer necessary following #120, since bounded channels have a
`try_ready` method we can rely on instead.

Note that this change is not entirely backwards compatible -- the error
type for a `Service` that is wrapped in `Buffer` must now be `Send +
Sync` so that it can safely be communicated back to callers.
Furthermore, `tower_buffer::Error::Closed` now contains the error that
the failed `Service` produced, which may trip up old code.
2019-01-16 11:31:42 -05:00
Sean McArthur
7b61c1fc19
tower-buffer: return spawn error instead of panic (#139) 2018-12-20 08:31:08 -08:00
Sean McArthur
ffa6f03618 tower-service v0.2.0 (#135) 2018-12-12 16:14:05 -05:00
Jon Gjengset
c1b96616b4
Don't make buffer::Worker block the reactor (#133)
Previously, `tower_buffer::Worker` would continue to loop indefinitely,
even if both the incoming request stream and the service returned
`NotReady`, starving the reactor in the process.
2018-12-06 13:10:10 -05:00
Jon Gjengset
6377702087
Make Buffer use a bounded channel (#120)
This change moves `Buffer` from `mpsc::unbounded` to `mpsc::channel`. The primary motivation for this change is that bounded channels provide back-pressure to callers, so that `Balance<Buffer>` for example works as expected. Currently, `Buffer` will accept as many requests as you can make for it without ever stopping down, slowly eating up all your memory.
2018-12-05 11:45:53 -05:00
Sean McArthur
801adb18db tower-buffer: fix Worker closing when service.poll_ready was NotReady 2018-12-03 12:39:11 -08:00
Jon Gjengset
c5cb47d612 Make Buffer::new use DefaultExecutor (#122)
Fixes #121.
2018-11-27 11:14:43 -08:00
Jon Gjengset
9bae225918 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:45 -08:00
Carl Lerche
75eecc476c
Switch Service request to a generic. (#109)
This changes the Service request type to a generic instead of an associated
type. This is more appropriate as requests are inputs to the service.

This change enables a single implementation of `Service` to accept many
kinds of request types. This also enables requests to be references.

Fixes #99
2018-11-01 12:28:10 -07:00
Sean McArthur
7dabd34d24
Tower Retry (#96)
- Inspect the request, response, and error when determining to retry
- Return a future if retry is desired
  - This future allows an impl to delay a retry
  - The future yields a new `Policy`, allowing state to be changed
    for later retries.
2018-08-28 11:05:15 -07:00
Sean McArthur
6cdc8d0ab5
buffer: check for canceled requests before polling inner service (#72) 2018-05-14 10:06:06 -07:00
Carl Lerche
5369879af6
Extract Service trait and related into crate. (#67)
This makes the `tower` crate available to be a "batteries included"
facade.
2018-04-25 12:35:52 -07:00
Eliza Weisman
8acbfa80ee Nested errors no longer print "inner service error:" or similar (#56) 2018-02-27 15:36:44 -08:00
Eliza Weisman
cc99f32486
Implement std::error::Error for Tower error types (#51)
I've implemented `std::error::Error` for the error types in the `tower-balance`, `tower-buffer`, `tower-in-flight-limit`, and `tower-reconnect` middleware crates.

This is required upstream for runconduit/conduit#442, and also just generally seems like the right thing to do as a library.
2018-02-24 10:48:04 -08:00
Oliver Gould
2db5adee43 Derive Debug for all error types (#28) 2017-11-19 12:25:10 -08:00
Carl Lerche
ad6ff8c0d8 License Tower under MIT only
A dual MIT / Apache 2.0 license does not make any sense. Since the
intent of the original license was to be dual under MIT or Apache 2.0,
restricting to ony MIT is OK.
2017-11-16 09:44:44 -08:00
Carl Lerche
8d6daa45ea Prevent accidental publishing of the crates 2017-11-16 09:40:32 -08:00
Eliza Weisman
f1a19a9b1e Fix crate name in README (#18) 2017-10-10 14:11:40 -07:00
Carl Lerche
87534a90de Initial buffer sketch (#13) 2017-10-10 10:38:40 -07:00