mirror of
https://github.com/tower-rs/tower.git
synced 2025-10-02 15:25:11 +00:00

FutureService::new
, with relaxed bounds (#523)
* util: add `FutureService::new`, with relaxed bounds There are a couple issues with the current implementation of `FutureService`. The first, and less important, is a minor usability issue: there's no `FutureService::new`, just a free function that returns `FutureService`. While the free function is nice in some cases, it means that if a user *is* naming the type someplace, they need to import `tower::util::future_service` *and* `tower::util::FutureService`, which is slightly annoying. Also, it just kind of violates the common assumption that most publicly constructable types have a `new`, requiring a look at the docs. The second, more significant issue is that the `future_service` function places a `Service` bound on the future's output type. While this is of course necessary for the *`Service` impl* on `FutureService`, it's not required to construct a `FutureService`. Of course, you generally don't want to construct a `FutureService` that *won't* implement service. However, the bound also means that additional generic parameters are now required at the site where the `FutureService` is constructed. In particular, the caller must now either know the request type, or be generic over one. In practice, when other middleware returns or constructs a `FutureService`, this essentially means that it's necessary to add a `PhantomData` for the request type parameter. This complicates code, and perhaps more importantly, increases compile times, especially with deeply-ensted middleware stacks. As an example of the downside of aggressive bounds at the constructor, it's worth noting that the implementation of `FutureService` currently in `tower` is based directly on a similar implementation in `linkerd2-proxy`. Except for the difference of whether or not the constructor has a `Service` bound on the future's output, the two implementations are very similar, almost identical. This gist shows some of the change necessary to replace our otherwise identical implementation with the `tower` version that bounds the `Service` type at construction-time: https://gist.github.com/hawkw/a6b07f9f4a8bce0c4b61036ed94114db This PR solves these issues by adding a `FutureService::new` constructor that does not introduce the `Service` bound. I didn't change the `future_service` function: I don't *think* removing bounds is a breaking change, but it is a modification to a publicly exposed function's type signature, so I'm a little leery about it. Also, I thought that the more aggressive bounding at construction-time might still be useful in simpler use-cases where the `FutureService` is not part of a more complex middleware stack, and that the free fn might be more likely to be used in those cases anyway. cc @davidpdrsn * relax bounds on free fn Signed-off-by: Eliza Weisman <eliza@buoyant.io> * Revert "relax bounds on free fn" This reverts commit 5ee4fd36c3d1849acede223218a1d457306b9247. This actually *is* breaking --- it would mean removing the `R` type parameter for the request type on the function. This changes the function definition, which might break uses of it.
Tower
Tower is a library of modular and reusable components for building robust networking clients and servers.
Overview
Tower aims to make it as easy as possible to build robust networking clients and servers. It is protocol agnostic, but is designed around a request / response pattern. If your protocol is entirely stream based, Tower may not be a good fit.
Status
Currently, tower 0.4
is released on crates.io.
License
This project is licensed under the MIT license.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Tower by you, shall be licensed as MIT, without any additional terms or conditions.
Description
Languages
Rust
100%