Skip to content

Commit

Permalink
fix(github): utilize RateLimitError.Rate
Browse files Browse the repository at this point in the history
  • Loading branch information
rgmz authored and Richard Gomez committed Oct 29, 2023
1 parent 3ffc0df commit 007c37c
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions pkg/sources/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -829,16 +829,22 @@ func (s *Source) scan(ctx context.Context, installationClient *github.Client, ch
// This will likely only be exhausted if many users/orgs are scanned without auth
func (s *Source) handleRateLimit(errIn error, res *github.Response) bool {
var (
now = time.Now()
knownWait = true
remaining = 0
retryAfter time.Duration
)

// GitHub has both primary (RateLimit) and secondary (AbuseRateLimit) errors.
var rateLimit *github.RateLimitError
var abuseLimit *github.AbuseRateLimitError
var (
rateLimit *github.RateLimitError
abuseLimit *github.AbuseRateLimitError
)
if errors.As(errIn, &rateLimit) {
// Do nothing
rate := rateLimit.Rate
if rate.Remaining == 0 {
retryAfter = rate.Reset.Sub(now)
}
} else if errors.As(errIn, &abuseLimit) {
retryAfter = abuseLimit.GetRetryAfter()
} else {
Expand All @@ -850,25 +856,33 @@ func (s *Source) handleRateLimit(errIn error, res *github.Response) bool {
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api#exceeding-the-rate-limit
if retryAfter <= 0 && res != nil {
var err error
remaining, err = strconv.Atoi(res.Header.Get("x-ratelimit-remaining"))
if err != nil {
knownWait = false

remainingHeader := res.Header.Get("x-ratelimit-remaining")
if remainingHeader != "" {
if remaining, err = strconv.Atoi(remainingHeader); err != nil {
knownWait = false
}
}

resetTime, err := strconv.Atoi(res.Header.Get("x-ratelimit-reset"))
if err != nil || resetTime == 0 {
knownWait = false
} else if resetTime > 0 {
retryAfter = time.Duration(int64(resetTime)-time.Now().Unix()) * time.Second
resetHeader := res.Header.Get("x-ratelimit-reset")
if resetHeader != "" {
resetTime, err := strconv.Atoi(resetHeader)
if err != nil || resetTime == 0 {
knownWait = false
} else if resetTime > 0 {
retryAfter = time.Duration(int64(resetTime)-now.Unix()) * time.Second
}
}
}

resumeTime := time.Now().Add(retryAfter).String()
var resumeTime string
if knownWait && remaining == 0 && retryAfter > 0 {
resumeTime = now.Add(retryAfter).String()
s.log.V(2).Info("rate limited", "retry_after", retryAfter.String(), "resume_time", resumeTime)
} else {
// TODO: Use exponential backoff instead of static retry time.
retryAfter = time.Minute * 5
resumeTime = now.Add(retryAfter).String()
// TODO: Use exponential backoff instead of static retry time.
s.log.V(2).Error(errIn, "unexpected rate limit error", "retry_after", retryAfter.String(), "resume_time", resumeTime)
}
time.Sleep(retryAfter)
Expand Down

0 comments on commit 007c37c

Please sign in to comment.