Skip to content

Commit 14ded34

Browse files
authored
Fix panic in rate limit (#226)
* Fix panic for division by zero and negative wait times * Rename function to something more descriptive
1 parent 8457b29 commit 14ded34

File tree

2 files changed

+19
-12
lines changed

2 files changed

+19
-12
lines changed

pkg/sync/syncer.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,17 @@ func shouldWaitAndRetry(ctx context.Context, err error) bool {
108108
details := st.Details()
109109
for _, detail := range details {
110110
if rlData, ok := detail.(*v2.RateLimitDescription); ok {
111-
wait = time.Until(rlData.ResetAt.AsTime())
112-
wait /= time.Duration(rlData.Limit)
111+
waitResetAt := time.Until(rlData.ResetAt.AsTime())
112+
duration := time.Duration(rlData.Limit)
113+
if duration == 0 {
114+
duration = 1
115+
}
116+
waitResetAt /= duration
113117
// Round up to the nearest second to make sure we don't hit the rate limit again
114-
wait = time.Duration(math.Ceil(wait.Seconds())) * time.Second
118+
waitResetAt = time.Duration(math.Ceil(waitResetAt.Seconds())) * time.Second
119+
if waitResetAt > 0 {
120+
wait = waitResetAt
121+
}
115122
}
116123
}
117124
}

pkg/uhttp/wrapper.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ func WithResponse(response interface{}) DoOption {
213213
}
214214
}
215215

216-
func GRPCWrap(preferredCode codes.Code, resp *http.Response, errs ...error) error {
216+
func WrapErrorsWithRateLimitInfo(preferredCode codes.Code, resp *http.Response, errs ...error) error {
217217
st := status.New(preferredCode, resp.Status)
218218

219219
description, err := ratelimit.ExtractRateLimitData(resp.StatusCode, &resp.Header)
@@ -296,25 +296,25 @@ func (c *BaseHttpClient) Do(req *http.Request, options ...DoOption) (*http.Respo
296296

297297
switch resp.StatusCode {
298298
case http.StatusRequestTimeout:
299-
return resp, GRPCWrap(codes.DeadlineExceeded, resp, optErrs...)
299+
return resp, WrapErrorsWithRateLimitInfo(codes.DeadlineExceeded, resp, optErrs...)
300300
case http.StatusTooManyRequests, http.StatusServiceUnavailable:
301-
return resp, GRPCWrap(codes.Unavailable, resp, optErrs...)
301+
return resp, WrapErrorsWithRateLimitInfo(codes.Unavailable, resp, optErrs...)
302302
case http.StatusNotFound:
303-
return resp, GRPCWrap(codes.NotFound, resp, optErrs...)
303+
return resp, WrapErrorsWithRateLimitInfo(codes.NotFound, resp, optErrs...)
304304
case http.StatusUnauthorized:
305-
return resp, GRPCWrap(codes.Unauthenticated, resp, optErrs...)
305+
return resp, WrapErrorsWithRateLimitInfo(codes.Unauthenticated, resp, optErrs...)
306306
case http.StatusForbidden:
307-
return resp, GRPCWrap(codes.PermissionDenied, resp, optErrs...)
307+
return resp, WrapErrorsWithRateLimitInfo(codes.PermissionDenied, resp, optErrs...)
308308
case http.StatusNotImplemented:
309-
return resp, GRPCWrap(codes.Unimplemented, resp, optErrs...)
309+
return resp, WrapErrorsWithRateLimitInfo(codes.Unimplemented, resp, optErrs...)
310310
}
311311

312312
if resp.StatusCode >= 500 && resp.StatusCode <= 599 {
313-
return resp, GRPCWrap(codes.Unavailable, resp, optErrs...)
313+
return resp, WrapErrorsWithRateLimitInfo(codes.Unavailable, resp, optErrs...)
314314
}
315315

316316
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
317-
return resp, GRPCWrap(codes.Unknown, resp, append(optErrs, fmt.Errorf("unexpected status code: %d", resp.StatusCode))...)
317+
return resp, WrapErrorsWithRateLimitInfo(codes.Unknown, resp, append(optErrs, fmt.Errorf("unexpected status code: %d", resp.StatusCode))...)
318318
}
319319

320320
if req.Method == http.MethodGet && resp.StatusCode == http.StatusOK {

0 commit comments

Comments
 (0)