Skip to content

Commit 0481d94

Browse files
fix(api-client): handle http.StatusTooManyRequests (#90)
* fix(api-client): handle http.StatusTooManyRequests * Update internal/scylla/client.go Co-authored-by: rjeczalik <rafal@rjk.io> --------- Co-authored-by: Dmitry Kropachev <dmitry.kropachev@scylladb.com> Co-authored-by: rjeczalik <rafal@rjk.io>
1 parent 1bfc3ff commit 0481d94

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

internal/scylla/client.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ import (
1111
"net/http"
1212
"net/url"
1313
stdpath "path"
14+
"strconv"
1415
"time"
1516

1617
"github.com/hashicorp/terraform-plugin-log/tflog"
1718
"github.com/scylladb/terraform-provider-scylladbcloud/internal/tfcontext"
1819
)
1920

20-
var (
21+
const (
2122
defaultTimeout = 60 * time.Second
2223
retriesAllowed = 3
2324
maxResponseBodyLength int64 = 1 << 20
@@ -130,7 +131,7 @@ func (c *Client) doHttpRequest(req *http.Request) (resp *http.Response, temporar
130131
return
131132
}
132133

133-
temporaryErr = resp.StatusCode == http.StatusBadGateway || resp.StatusCode == http.StatusGatewayTimeout
134+
temporaryErr = resp.StatusCode == http.StatusBadGateway || resp.StatusCode == http.StatusGatewayTimeout || resp.StatusCode == http.StatusTooManyRequests
134135
return
135136
}
136137

@@ -140,12 +141,36 @@ func (c *Client) doHttpRequestWithRetries(req *http.Request, retries int, retryB
140141
if err == nil {
141142
_ = resp.Body.Close() // We want to retry anyway.
142143
}
144+
var timeToSleep time.Duration
145+
if d, ok := parseRetryAfter(resp.Header.Get("Retry-After")); ok {
146+
timeToSleep = d
147+
} else {
148+
timeToSleep = retryBackoffDuration
149+
}
150+
timer := time.NewTimer(timeToSleep)
151+
defer timer.Stop()
152+
select {
153+
case <-timer.C:
154+
case <-req.Context().Done():
155+
return nil, req.Context().Err()
156+
}
157+
143158
return c.doHttpRequestWithRetries(req, retries-1, retryBackoffDuration*2)
144159
}
145160

146161
return resp, err
147162
}
148163

164+
func parseRetryAfter(val string) (time.Duration, bool) {
165+
if n, err := strconv.ParseUint(val, 10, 64); err == nil {
166+
return time.Duration(n) * time.Second, true
167+
}
168+
if t, err := time.Parse(time.RFC1123, val); err == nil {
169+
return time.Until(t), true
170+
}
171+
return 0, false
172+
}
173+
149174
func (c *Client) callAPI(ctx context.Context, method, path string, reqBody, resType interface{}, query ...string) error {
150175
ctx = tfcontext.AddHttpRequestInfo(ctx, method, path)
151176
req, err := c.newHttpRequest(ctx, method, path, reqBody, query...)

0 commit comments

Comments
 (0)