Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

util: Add then combinator #500

Merged
merged 21 commits into from
Jan 4, 2021
Merged

util: Add then combinator #500

merged 21 commits into from
Jan 4, 2021

Conversation

hawkw
Copy link
Member

@hawkw hawkw commented Dec 28, 2020

Currently, ServiceExt and ServiceBuilder provide combinators for
mapping successful responses to other responses, and mapping errors to
other errors, but don't provide a way to map between Ok and Err
results.

For completeness, this branch adds a new then combinator, which takes
a function from Result to Result and applies it when the service's
future completes. This can be used for recovering from some errors or
for rejecting some Ok responses. It can also be used for behaviors
that should be run when a service's future completes regardless of
whether it completed successfully or not.

Depends on #499

Currently, the `ServiceExt` trait has `with` and `try_with` methods for
composing a `Service` with functions that modify the request type, and
`map_err` and `map_ok` methods for composing a service with functions
that modify the response type. Meanwhile, `ServiceBuilder` has
`map_request` for composing a service with a request mapping function,
and `map_response` for composing a service with a response-mapping
function. These combinators are very similar in purpose, but are
implemented using different middleware types that essentially duplicate
the same behavior.

Before releasing 0.4, we should probably unify these APIs. In
particular, it would be good to de-duplicate the middleware service
types, and to unify the naming.

This commit makes the following changes:
- Rename the `ServiceExt::with` and `ServiceExt::try_with` combinators
  to `map_request` and `try_map_request`
  - Rename the `ServiceExt::map_ok` combinator to `map_response`
- Unify the `ServiceBuilder::map_request` and `ServiceExt::map_request`
  combinators to use the same `Service` type
- Unify the `ServiceBuilder::map_response` and
  `ServiceExt::map_response` combinators to use the same `Service` type
- Unify the `ServiceBuilder::map_err` and `ServiceExt::map_err`
  combinators to use the same `Service` type
- Only take `FnOnce + Clone` when in response/err combinators, which
  require cloning into the future type. `MapRequest` and `TryMapRequest`
  now take `FnMut(Request)`s and don't clone them every time they're
  called
- Reexport future types for combinators where it makes sense.
- Add a `try_map_request` method to `ServiceBuilder`

Closes #498
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
@hawkw hawkw self-assigned this Dec 28, 2020
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Currently, `ServiceExt` and `ServiceBuilder` provide combinators for
mapping successful responses to other responses, and mapping errors to
other errors, but don't provide a way to map between `Ok` and `Err`
results.

For completeness, this branch adds a new `then` combinator, which takes
a function from `Result` to `Result` and applies it when the service's
future completes. This can be used for recovering from some errors or
for rejecting some `Ok` responses. It can also be used for behaviors
that should be run when a service's future completes regardless of
whether it completed successfully or not.

Depends on #499
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
@hawkw hawkw force-pushed the eliza/then-combinator branch from d2a0f29 to 1f17c94 Compare December 28, 2020 23:01
@hawkw hawkw mentioned this pull request Dec 28, 2020
2 tasks
@olix0r
Copy link
Collaborator

olix0r commented Dec 28, 2020

This seems somewhat incongruous with Futures::then, which takes a closure that produces another future. Should this behave similarly? This would permit more flexible uses, like calling another future in the then block.

What we have here seems to be more like Futures::map

@hawkw
Copy link
Member Author

hawkw commented Dec 28, 2020

This seems somewhat incongruous with Futures::then, which takes a closure that produces another future. Should this behave similarly? This would permit more flexible uses, like calling another future in the then block.

What we have here seems to be more like Futures::map

This is a good point --- I got the naming mixed up. then should definitely be async, and a synchronous version of this can be implemented on top of it.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Currently, `ServiceExt` and `ServiceBuilder` provide combinators for
mapping successful responses to other responses, and mapping errors to
other errors, but don't provide a way to map between `Ok` and `Err`
results.

For completeness, this branch adds a new `then` combinator, which takes
a function from `Result` to `Result` and applies it when the service's
future completes. This can be used for recovering from some errors or
for rejecting some `Ok` responses. It can also be used for behaviors
that should be run when a service's future completes regardless of
whether it completed successfully or not.

Depends on #499
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Copy link
Member

@LucioFranco LucioFranco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, minor comments

tower/src/util/mod.rs Show resolved Hide resolved
@@ -327,6 +542,17 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
{
TryMapRequest::new(self, f)
}

/// TODO(eliza): docs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing docs

tower/src/util/then.rs Outdated Show resolved Hide resolved
Base automatically changed from eliza/unify-combinators to master January 4, 2021 18:27
hawkw added 5 commits January 4, 2021 10:28
…o eliza/then-combinator

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
@hawkw hawkw merged commit bef0ade into master Jan 4, 2021
@hawkw hawkw deleted the eliza/then-combinator branch January 4, 2021 19:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants