-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
Rewrite util/retry as a for-loop #1396
Conversation
if err := gogoproto.Unmarshal(b, call.Reply); err != nil { | ||
return retry.Continue, err | ||
if err = gogoproto.Unmarshal(b, call.Reply); err != nil { | ||
continue |
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.
the error should be logged.
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.
Done.
I like this approach, though the diff also showcases that it's much less elegant when the retryable code has a lot of |
} | ||
|
||
defer resp.Body.Close() |
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.
Defers work at function scope, not block scope. With this pattern response bodies won't get closed until the last retry has completed. (and in go's http client, failing to close a response body prevents that connection from being reused). When a retry loop contains a defer, I think we need to refactor the body into a separate function.
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.
in go's http client, failing to close a response body prevents that connection from being reused
Ah, I didn't know this (and was otherwise fine with closing at the very end of the function). I'll fix this up.
I didn't look at the implementation in depth, but the for-loop API looks good to me. |
This sounds nice, but I think providing this choice is a mistake. It's just not the Go way; if a situation calls for this, this facility can trivially be written inline, and the sugar will just serve to obfuscate in this case. |
Not sure the "Go way" mandates repeating yourself without a good reason, and it's a bit much to inline. Let's just see how far you get, no need to add it prematurely. |
OK, this is finally complete. PTAL! |
InitialBackoff: 1 * time.Millisecond, | ||
MaxBackoff: 5 * time.Millisecond, | ||
Multiplier: 2, | ||
MaxRetries: 2, |
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.
does MaxRetries=2
correspond to MaxAttempts=3
?
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.
Gah, no, it's off by one
LGTM |
Pushed some commits to address all the feedback. I'll squash and merge when this is green. @spencerkimball mind taking a look? |
|
||
// Retry implements the public methods necessary to control an exponential- | ||
// backoff retry loop. | ||
type Retry struct { |
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.
It would be helpful to have a usage example in comments.
Rewrite util/retry as a for-loop
The final proposal! PTAL.