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

Use a max retry after duration for secondary rate limit if specified #3438

Conversation

Letiste
Copy link
Contributor

@Letiste Letiste commented Jan 17, 2025

The current logic to pick a retry after duration in case of a secondary rate limit is to first check for the retry after header, and if not found, use the primary rate limit reset time. As the primary rate limit reset every hour, we can be blocked for as long as 1 hour when GitHub returns a secondary rate limit error without a retry after header.

According to GitHub documentation, the rate limit reset header should be used when the remaining allowed requests reached 0. Otherwise, retry in 1 min (doc):

If you receive a rate limit error, you should stop making requests temporarily according to these guidelines:

  • If the retry-after response header is present, you should not retry your request until after that many seconds has elapsed.
  • If the x-ratelimit-remaining header is 0, you should not make another request until after the time specified by the x-ratelimit-reset header. The x-ratelimit-reset header is in UTC epoch seconds.
  • Otherwise, wait for at least one minute before retrying. If your request continues to fail due to a secondary rate limit, wait for an exponentially increasing amount of time between retries, and throw an error after a specific number of retries.

This PR adds an optional max wait time for the secondary rate limit that will, if specified, prevents the client to block up to 1h in some cases.

Given that the GitHub documentation specifies to use the rate limit reset header only if there is no more requests remaining in the quota, I was tempted to make this change by default but it would change the current behaviour. Should we make it by default regardless?

@@ -174,6 +174,10 @@ type Client struct {
rateLimits [Categories]Rate // Rate limits for the client as determined by the most recent API calls.
secondaryRateLimitReset time.Time // Secondary rate limit reset for the client as determined by the most recent API calls.

// If specified, Client will block requests for at most this duration in case of reaching a secondary
// rate limit
MaxSecondaryRateLimitRetryAfterDuration time.Duration
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm letting users specify their desired max duration. We could enforce a minimum or a default value here if we want to make sure users are not using this field incorrectly

Comment on lines +927 to +930
// if a max duration is specified, make sure that we are waiting at most this duration
if c.MaxSecondaryRateLimitRetryAfterDuration > 0 && rerr.GetRetryAfter() > c.MaxSecondaryRateLimitRetryAfterDuration {
rerr.RetryAfter = &c.MaxSecondaryRateLimitRetryAfterDuration
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to enforce the max duration in the parseSecondaryRate function but we don't have access to the client there, and it was tedious to pass a parameter downstream so I'm mutating the error here instead. Let me know if you would prefer another solution

@Letiste Letiste marked this pull request as ready for review January 17, 2025 11:05
@Letiste Letiste changed the title Use max retry after duration for secondary rate limit Use a max retry after duration for secondary rate limit if specified Jan 17, 2025
Copy link

codecov bot commented Jan 17, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.26%. Comparing base (2b8c7fa) to head (b810986).
Report is 245 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3438      +/-   ##
==========================================
- Coverage   97.72%   92.26%   -5.46%     
==========================================
  Files         153      174      +21     
  Lines       13390    15026    +1636     
==========================================
+ Hits        13085    13864     +779     
- Misses        215     1068     +853     
- Partials       90       94       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Verified

This commit was signed with the committer’s verified signature.
Letiste Léo Salé
@Letiste Letiste force-pushed the leo.sale/max-retry-after-duration-secondary-rate-limit branch from 3e7ca0d to b810986 Compare January 17, 2025 12:09
@gmlewis
Copy link
Collaborator

gmlewis commented Jan 17, 2025

I am extremely leery of changing the default behavior regarding rate limiting.
If you want to provide an option for your feature, I'm fine with that.

@wmouchere - please comment on this PR because of your recent work on #3411.

Copy link
Collaborator

@gmlewis gmlewis left a comment

Choose a reason for hiding this comment

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

Thank you, @Letiste.
LGTM.

Awaiting second LGTM+Approval from any other contributor to this repo before merging.

@gmlewis gmlewis added the NeedsReview PR is awaiting a review before merging. label Feb 5, 2025
Copy link
Contributor

@stevehipwell stevehipwell left a comment

Choose a reason for hiding this comment

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

LGTM

@gmlewis
Copy link
Collaborator

gmlewis commented Feb 5, 2025

Thank you, @stevehipwell!
Merging.

@gmlewis gmlewis removed the NeedsReview PR is awaiting a review before merging. label Feb 5, 2025
@gmlewis gmlewis merged commit a4333f3 into google:master Feb 5, 2025
6 of 7 checks passed
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.

None yet

3 participants