-
Notifications
You must be signed in to change notification settings - Fork 282
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
improve flexiblity of retry policy #584
Conversation
retry::Policy is an effective way to expressing retries, however, there two use cases that as it stands today, cannot be expressed: - Altering the final response (eg. to record the fact that you ran out of retries) - Altering the request (eg. to set a header to the server indicating that this request is a retry) (Technically the second is possible with `clone_request`, but it's a little unclear _which_ request would actually get sent). This change implements what I think is pretty close to the minimal update to make this possible, namely, `req` and `Res` both become mutable references. This enables policies to mutate them during execution & enables both of the use cases above without complicating the "simple path" callers who don't need this behavior. **This is a breaking change.** However, the fixes are only a couple of `&mut` and potentially a call to `as_ref()`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have never used this middleware in practice but to me the change looks sensible. Though I'm wondering if someone else with more experience using Retry
has run into other problems that could be solved, should we decide to make a breaking change. cc @hawkw @olix0r @LucioFranco @seanmonstar
Had one small suggestion/question.
I've also considered (and would be totally happy) with an API that "mapped" over req & res, taking and returning ownership. This may actually even be slightly more flexible. However, I didn't want to leak this detail onto all users.
To return a new request/response the future returned by Policy::retry
would have to change as well which might be too much of a change.
@@ -58,7 +58,7 @@ pub trait Policy<Req, Res, E>: Sized { | |||
/// | |||
/// [`Service::Response`]: crate::Service::Response | |||
/// [`Service::Error`]: crate::Service::Error | |||
fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future>; | |||
fn retry(&self, req: &mut Req, result: &mut Result<Res, E>) -> Option<Self::Future>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess getting a &mut Result<Res, E>
allows users to change Err(_)
into Ok(_)
which might be kinda odd. Not sure. Feels like getting Result<&mut Res, &mut E>
would fit the use-cases as well but not allow changing the Result
variant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah, that is a really good point david, what do you think about that @rcoh ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment wasn't threaded because of email:
The entire point is to change the variant (at least for me). Because there
are "success" cases the actually need to be retries and when I run out of
retries I need to change it to failure
The entire point is to change the variant (at least for me). Because there
are "success" cases the actually need to be retries and when I run out of
retries I need to change it to failure
…On Sun, May 2, 2021, 8:13 AM David Pedersen ***@***.***> wrote:
***@***.**** commented on this pull request.
I have never used this middleware in practice but to me the change looks
sensible. Though I'm wondering if someone else with more experience using
Retry has run into other problems that could be solved, should we decide
to make a breaking change. cc @hawkw <https://github.com/hawkw> @olix0r
<https://github.com/olix0r> @LucioFranco <https://github.com/LucioFranco>
@seanmonstar <https://github.com/seanmonstar>
Had one small suggestion/question.
I've also considered (and would be totally happy) with an API that
"mapped" over req & res, taking and returning ownership. This may actually
even be slightly more flexible. However, I didn't want to leak this detail
onto all users.
To return a new request/response the future returned by Policy::retry
would have to change as well which might be too much of a change.
------------------------------
In tower/src/retry/policy.rs
<#584 (comment)>:
> @@ -58,7 +58,7 @@ pub trait Policy<Req, Res, E>: Sized {
///
/// [`Service::Response`]: crate::Service::Response
/// [`Service::Error`]: crate::Service::Error
- fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future>;
+ fn retry(&self, req: &mut Req, result: &mut Result<Res, E>) -> Option<Self::Future>;
I guess getting a &mut Result<Res, E> allows users to change Err(_) into
Ok(_) which might be kinda odd. Not sure. Feels like getting Result<&mut
Res, &mut E> would fit the use-cases as well but not allow changing the
Result variant.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#584 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADYKZZKITAKKYCN6H47VJ3TLU6YBANCNFSM435NQWHQ>
.
|
Alright cool. That does make sense. I kinda feel like if we are going to make a breaking change we should take care to design something that we are happy with. That might be this or it might be bigger changes. I haven't used Retry personally so I don't know which it is. There was some discussion about other potential changes to Retry here. |
@rcoh maybe I am forgetting how this works but can't you return an error in the returned service future? |
@LucioFranco you have a mut ref to the result, so you can |
i actually just ran into a use-case for a mutable request in the approach i was going to take was storing the buffered body on the initial request, and then sending the buffer on a |
@hawkw just to clarify, in this change the request becomes mutable in the Which is why I made it mutatable in |
oh, i misread the PR description, whoops! i'm going to just go ahead and try to implement a lazily buffered request body against this branch and report back? i think it may still be possible without also touching another option would be to make the |
It would be really nice to get this change into 0.5 (which we're currently working on). @rcoh, are you interested in updating this branch to build with the latest |
I can do the merge tomorrow assuming there's nothing too problematic |
merge is done. I also added another section of docs about the mutable fields—I assume you'll squash merge, but if not let me know and I can cleanup history |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some minor documentation suggestions, hope they're helpful!
tower/src/retry/policy.rs
Outdated
/// | ||
/// The policy MAY chose to mutate the result. This can enable the retry policy to convert a failure | ||
/// into a success and vice versa. For example, if the policy is used to poll while waiting for a state | ||
/// change, you can switch the result to failure such that running out of retries returns a specific failure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: in general, we prefer to avoid second-person ('you') language in docs:
/// change, you can switch the result to failure such that running out of retries returns a specific failure. | |
/// change, the policy can switch the result to failure such that running out of retries returns a specific failure. |
Yeah, that's right, we generally merge PRs by squashing, so you don't have to worry about it! :) |
- Wrap docs to 80 characters - Small doc tweaks / rewrites to clarify & remove `you`
…exible-retry-policy
retry::Policy
is an effective way to expressing retries, however, there two use cases thatas it stands today, cannot be expressed:
(Technically the second is possible with
clone_request
, but it's a little unclear which request would actually get sent).This change implements what I think is pretty close to the minimal update to make this possible, namely,
req
and
Res
both become mutable references. This enables policies to mutate them during execution & enables both of theuse cases above without complicating the "simple path" callers who don't need this behavior.
This is a breaking change. However, the fixes are only a couple of
&mut
and potentially a call toas_ref()
.I've also considered (and would be totally happy) with an API that "mapped" over req & res, taking and returning ownership. This may actually even be slightly more flexible. However, I didn't want to leak this detail onto all users.