* tower: prepare to release 0.4.10
- Fix accidental breaking change when using the
`rustdoc::broken_intra_doc_links` lint ([#605])
- Clarity that tower's minimum supported rust version is 1.46 ([#605])
[#605]: https://github.com/tower-rs/tower/pull/605
* Update tower/CHANGELOG.md
Co-authored-by: Oliver Gould <ver@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
* Actually check MSCV on CI
* check broken_intra_doc_links on CI
* clean up CI
* fix other crates
* bump MSRV to 1.42 because of tracing-core
* attempt to fix http not working on 1.42
* use `--workspace` instead of `--all`
`--all` is deprecated
* make tower-service build on 1.42
* force http version 0.2.4
* actually msrv is 1.46 because of tokio
* fix running `cargo fmt`
* clean up
* also run tests on 1.46
* ignore rustsec in time
* REMOVE ME updates peak_wema test to pass
* adds pin_project_lite dependency
* uses pin_project_lite for load::Constant
* uses pin_project_lite for load::PencingRequestsDiscover
* uses pin_project_lite for load::PeakEwma
* uses pin_project_lite for load::Completion
* uses pin_project_lite for tests::support::IntoStream
Turns IntoStream into a regular struct because pin_project_lite does not and will support tuple structs.
416be96f77/src/lib.rs (L401-L408)
* refactors opaque_future into a regular struct
This enables migration to pin_project_lite, which does not and will not support tuple structs
416be96f77/src/lib.rs (L401-L408)
* migrates opaque_future to use pin_project_lite
* removes tuple variant from load_shed::ResponseState enum
* migrates load_shed::future to pin_project_lite
* removes tuple variant from filter::future::State
* migrates filter::future to pin_project_lite
Note: the doc comment on AsyncResponseFuture::service was also reduced to a regular comment.
This is a known limitation of pin_project_lite that the they have labeled as "help wanted".
https://github.com/taiki-e/pin-project-lite/issues/3#issuecomment-745194112
* migrates retry::Retry to pin_project_lite
* refactors retry::future::State to enable pin_project_lite
pin_project_lite has the current limitation of nto supporting doc comments
https://github.com/taiki-e/pin-project-lite/issues/3#issuecomment-745194112
pin_project_lite does not and will not support tuple variants
416be96f77/src/lib.rs (L401-L408)
* migrates retry::future to pin_project_lite
* migrates spawn_ready::make to pin_project_lite
* refactors buffer::future::ResponseState to allow pin_project_lite
* migrates buffer::future to pin_project_lite
* refactors util::AndThenFuture to allow pin_project_lite
* migrates util::AndThenFuture to pin_project_lite
* migrates hedge::Future to pin_project_lite
* migrates hedge::select::ResponseFuture to pin_project_lite
* refactors hedge::delay enum for pin_project_lite
* refactors reconnect::future enum for pin_project_lite
* refactors oneshot::State enum for pin_project_lite
* migrates util::oneshot to pin_project_lite
* migrates reconnect::future to pin_project_lite
* migrates hedge::delay to pin_project_lite
* migrates hedge::latency to pin_project_lite
* migrates discover::list to pin_project_lite
* migrates timeout::future to pin_project_lite
* migrates balance::pool to pin_project_lite
* migrates balance::p2c::make to pin_project_lite
* migrates balance::p2c::service to pin_project_lite
* migrates call_all::ordered to pin_project_lite
* migrates call_all::common to pin_project_lite
* migrates call_all::unordered to pin_project_lite
* migrates util::optional::future to pin_project_lite
* migrates limit::concurrency::future to pin_project_lite
* migrates tower-balance example to pin_project_lite
* applies cargo fmt
* migrates tower-test to pin_project_lite
* fixes cargo hack check
peak_wma and pending_requests will now properly compile without the "discover" feature enabled.
* fixes lint rename warning on nightly
broken_intra_doc_links has been renamed to rustdoc::broken_intra_doc_links
* migrates buffer::Worker to pin_project_lite
pin_project_lite does support PinnedDrop
https://github.com/taiki-e/pin-project-lite/pull/25/files
However, it does not support generic trait bounds on the PinnedDrop impl.
To workaround this, I removed the T::Error bound from the Worker struct definition,
and moved `close_semaphore` to a a new impl without that trait bound.
* fixes abort_on_drop test
This test was also failing on master.
* applies cargo fmt
This adds a guide that explains how to implement a middleware from scratch without taking any shortcuts. It walks through implementing `Timeout` as it exists in Tower today.
The hope is that once users have read [the previous guide](https://tokio.rs/blog/2021-05-14-inventing-the-service-trait) followed by this one they should be fully equipped to implement their own middleware.
* limit: global concurrency limit layer from a owned semaphore
* new_owned -> new_shared + docs improvements
Co-authored-by: David Pedersen <david.pdrsn@gmail.com>
* keep exposing Semaphore, but rename the API a bit and make it simpler to use
* missed a spot
* minor docs fixes
* update changelog
Co-authored-by: David Pedersen <david.pdrsn@gmail.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
This adds the first Tower guide called "Inventing the `Service` trait". It attempts to motivate all the parts to `Service` by walking the user through how they could have invented `Service` themselves, from scratch. It goes into quite a bit of detail but hopefully it paints a somewhat complete picture in the end.
The next guide I want to write is about how to implement a proper `Timeout` middleware using `Layer`, pin-project, and all the bells and whistles.
Ref: https://github.com/tower-rs/tower/issues/33
# 0.4.7 (April 27, 2021)
### Added
- **builder**: Add `ServiceBuilder::check_service` to check the request,
response, and error types of the output service. ([#576])
- **builder**: Add `ServiceBuilder::check_service_clone` to check the
output service can be cloned. ([#576])
### Fixed
- **spawn_ready**: Abort spawned background tasks when the `SpawnReady`
service is dropped, fixing a potential task/resource leak (#[581])
- Fixed broken documentation links ([#578])
[#576]: https://github.com/tower-rs/tower/pull/576
[#578]: https://github.com/tower-rs/tower/pull/578
[#581]: https://github.com/tower-rs/tower/pull/581
The `SpawnReady` service spawns a background task whenever the inner
service is not ready; but when the `SpawnReady` service is dropped, this
task continues to run until it becomes ready (at which point the ready
service will be dropped). This can cause resource leaks when the inner
service never becomes ready.
This change adds a `Drop` implementation for the `SpawnReady` service
that aborts the background task when one is present.
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
I've run into a use case where I need to return a `Layer` with a complex
type from a function. I previously used `impl Layer<S, Service = impl
Service<...>>` but that impacted compile times quite significantly.
Boxing the `Layer` fixed it. Thought it made sense to upstream.
The `Send + Sync + 'static` bounds on the inner `dyn Layer` were
necessary to get it working with hyper.
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
* builder: Add `ServiceBuilder::service_fn`
A small convenience for doing `.service(service_fn(handler_function))`.
* Docs tweaks
* Apply suggestions from code review
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
* Fix
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
This PR renames:
- `ServiceExt::ready_and` to `ServiceExt::ready`
- the `ReadyAnd` future to `Ready`
- the associated documentation to refer to `ServiceExt::ready`
and `ReadyAnd`.
This PR deprecates:
- the `ServiceExt::ready_and` method
- the `ReadyAnd` future
These can be removed in Tower 0.5.
My recollection of the original conversation surrounding the
introduction of the `ServiceExt::ready_and` combinator in
https://github.com/tower-rs/tower/pull/427 was that it was meant to be a
temporary workaround for the unchainable `ServiceExt::ready` combinator
until the next breaking release of the Tower crate. The unchainable
`ServiceExt::ready` combinator was removed, but `ServiceExt::ready_and`
was not renamed. I believe, but am not 100% sure, that this was an
oversight.
* builder: Add `ServiceBuilder::map_future`
I forgot at add this one in #542. Think its nice to have for
consistency.
* Update tower/src/builder/mod.rs
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
Currently, when using `SpawnReady`, the current `tracing` span is not
propagated to the spawned task when the inner service is not ready. This
means that any traces emitted by the inner service's `poll_ready` occur
in their own root span, rather than the span the `SpawnReady` service
was polled in.
This branch fixes this by propagating the current trace span to the
spawned task.
This means that "spawn-ready" now enables the "tracing" feature. In the
future, we may want to consider feature-flagging `tracing` separately
from the middleware implementation that contain tracing instrumentation,
but doing so would break traces if the feature flag isn't enabled. This
doesn't break API compatibility, but it *does* break functionality, so
we may not want to do that until the next breaking change release.
I also added tests for span propagation. I realized the same test could
easily be applied to `Buffer`, which also propagates `tracing` spans, to
guard against regressions, so I also added a test for buffer.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
* make: Add `Shared`
Fixes https://github.com/tower-rs/tower/issues/262
`Shared` is a `MakeService` that produces services by cloning an inner
service.
* Fix build with different set of features
* Formatting
* Make `Shared` generic over any target
* Fix tests
* Move `Shared` into its own file
* Add example
* Add `util::option_layer` and `ServiceBuilder::option_layer`
Closes#553
* Apply suggestions to improve the docs
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
The [`Semaphore` implementation in `tokio::sync`][1] doesn't expose a
`poll_acquire` method to acquire owned semaphore permits in a
non-async-await context. Currently, the `limit::concurrency` and
`buffer` middleware use our own pollable wrapper for
`tokio::sync::Semaphore`. This works by creating a new
`Semaphore::acquire_owned` future and boxing it every time the semaphore
starts acquiring a new permit.
Recently, the `tokio_util` crate introduced its own [`PollSemaphore`
wrapper type][2]. This provides the same functionality of a pollable
version of `tokio::sync`'s `Semaphore`, just like our semaphore wrapper.
However, `tokio_util`'s version is significantly more efficient: rather
than allocating a new `Box` for _each_ `acquire_owned` future, it uses
the [`ReusableBoxFuture` type][3] to reuse a *single* allocation every
time a new `acquire_owned` future is needed. This means that rather than
allocating *every* time a `Buffer` or `ConcurrencyLimit` service starts
acquiring a new permit, there's a single allocation for each clone of
the service. Unless services are cloned per-request, this means that the
allocation is moved out of the request path in most cases.
I had originally considered an approach similar to this, but I didn't
think the reduced allocations were worth adding a bunch of unsafe code
in `tower` (which presently contains no unsafe code). However, this type
fits in perfectly in `tokio-util`, and now that there's an upstream
implementation, we should use it.
This introduces a dependency on `tokio-util` when the "limit" or "buffer"
features are enabled.
Additionally, I've added a new test for `Buffer` asserting that once an
individual `Buffer` service has been driven to readiness but not called,
additional `poll_ready` calls won't acquire additional buffer capacity.
This reproduces a bug that existed in earlier versions of
`tower::buffer`, which could result in starvation of buffer waiters.
This bug doesn't exist in 0.4, but I wanted to ensure that changing the
buffer internals here didn't introduce any new regressions.
[1]: https://docs.rs/tokio/1.2.0/tokio/sync/struct.Semaphore.html
[2]: https://docs.rs/tokio-util/0.6.3/tokio_util/sync/struct.PollSemaphore.html
[3]: https://docs.rs/tokio-util/0.6.3/src/tokio_util/sync/poll_semaphore.rs.html#13-16
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
* util: Add `ServiceExt::map_future`
I ran into a thing today where I wanted to write a middleware that wraps
all futures produced by a service in a `tracing::Span`. So something
like `self.inner.call(req).instrument(span)`.
Afaik all the combinators we have today receive the value produced by
the future and not the future itself. At that point its too late to call
`.instrument`. So I thought this made sense to add a combinator for.
* Add additional trait bounds to improve UX
* Add docs
* Update changelog
* Clean up debug impl
* Better debug impl for `MapFutureLayer`
This branch adds to the "Usage" section in the `tower` crate's README
and lib.rs docs. In particular, I've added a discussion of the various
use-cases for Tower, and a list of crates that support Tower.
Let me know if I'm missing anything!
* Add "full" feature that turns on all other features
Fixes https://github.com/tower-rs/tower/issues/530
* Don't include "log" feature in "full"
Makes it easier to disable "log" since its already included in the
default feature set.
* Fix changelog
This change modifies the `SpawnReady` service to track a
`tokio::task::JoinHandle` instead of creating a `tokio::sync::oneshot`
on each pending poll. This avoid unnecessary allocation.
The `spawn_ready` test is also fixed to avoid using `thread::sleep`,
instead using `tokio::time::pause`.