-
Notifications
You must be signed in to change notification settings - Fork 271
feat: RetryAttempt in PrepareRetry hook #258
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
base: main
Are you sure you want to change the base?
Conversation
client.go
Outdated
@@ -399,7 +399,7 @@ type Backoff func(min, max time.Duration, attemptNum int, resp *http.Response) t | |||
type ErrorHandler func(resp *http.Response, err error, numTries int) (*http.Response, error) | |||
|
|||
// PrepareRetry is called before retry operation. It can be used for example to re-sign the request | |||
type PrepareRetry func(req *http.Request) error | |||
type PrepareRetry func(req *http.Request, numTries int) error |
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.
Question: Can you elaborate the scenario where we will need to know the current trial count ?
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.
Hi, I have the following scenarios:
- We can send this value in the header,
X-RetryableHTTP-Retry
, and the client can use this information for adaptive throttling, logging, or retrying these requests differently. - Based on the retry count, we can mutate the host (a fallback URL, similar to DLQ concepts), etc.
There might be more use cases, but I opened this PR because of the above two scenarios.
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.
Breaking Change?
Seems like the the function is mutated as a result the function signature has changed. Which Technically breaks backward compatibility with any code that was using the old version.
To me it seems like a breaking change. Can we add a new hook instead of changing the existing one? Or keep the old version working behind the scenes — for example, check if the old hook is set and call it if the new one isn’t used.
Either way, it is good idea to document this change clearly, in the changelog, release notes, or even just in a comments, so others aren’t caught off guard.
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.
@CreatorHead
Yes, it is a breaking change, so I am open to either of the following approaches:
- Document it as a breaking change so that when people upgrade, they can update it. Also, the build step will fail, which would be caught in the CI stage / local, preventing unexpected issues.
- Introduce a new hook
PrepareForRetry(req, retryAttempt)
and mark the current hookPrepareRetry(req)
deprecate to remove it from future releases.
I prefer the first option. Let me know the final decision so I can make the changes accordingly.
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.
@avmnu-sng, thanks for laying out the options!
Let’s avoid the breaking change for now:
- Keep
PrepareRetry(req)
as a thin shim that delegates to the new
PrepareForRetry(req, attempt)
(withattempt
defaulting to1
). - Add a
// Deprecated:
tag plus a lint/staticcheck rule so users see a warning, not an error. - Document the deprecation in the release notes and set a removal target.
That gives everyone a smooth upgrade path while still moving us to the richer API. Thanks!
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.
@CreatorHead Sure, I can add PrepareForRetry
. We won't be able to use PrepareRetry(req)
as a delegator. The implementation would now be something like (which I believe is what you meant):
if c.PrepareForRetry != nil {
c.PrepareForRetry(req, attempt)
} else if c.PrepareRetry != nil {
c.PrepareRetry(req)
}
Also, I don't think, we have a RELEASE_NOTES.md
. For now, I will update the CHANGELOG.md
to include a TO RELEASE section and add the deprecation note and target it for removal in v8.0.0?
The Staticcheck SA1019 will pick up the deprecation warning when run. I don't see a config to disable it, so no additional work is needed.
Adding the `retryAttempt` counter, which refers to the current retry attempt to enable the server and client to make an informed decision to process the request. For example, - The client can hit a fallback host (server) based on the retry attempt. - The client can send the retry count in the header, and the server can process the request in any special way.
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.
Thanks for the update — the changes to PrepareRetry
look solid overall, but a few tweaks would help polish things up:
Suggested Changes
-
Docs & Comments
The newretryAttempt
param is a great addition, but it needs a brief comment explaining its purpose. Some of the existing comments (e.g., aroundPrepareRetry
) could also be trimmed for clarity. -
Error Context
WhenPrepareRetry
fails, consider wrapping the error with context (e.g., which attempt failed) to make debugging easier. -
Naming
prepareChecks
could be renamed to something clearer likeprepareRetryCount
to better reflect its purpose. -
Header Logic
A short comment on why the retry count is set in the header would help future readers. -
Test Coverage
Please double-check that the retry logic is well-covered by tests, especially the new param behavior.
Let me know if you’d like help with any of these. Almost there!
@CreatorHead, I am sorry, but I am confused now. Do you want me to go ahead with the breaking change now? No adding another hook #258 (comment)? I follow a minimal change philosophy. The Renaming, updating how errors are handled, etc., are outside the scope of adding a retry counter parameter, which must be done separately. |
Adding the retryAttempt counter, which refers to the current retry attempt to enable the server and client to make an informed decision to process the requests. For example,