@@ -8,11 +8,7 @@ import (
88 "io"
99 "net/http"
1010 "net/url"
11- "strconv"
1211 "strings"
13- "time"
14-
15- "github.com/buildkite/roko"
1612)
1713
1814// ErrorResponse represents an error response from the API
@@ -44,10 +40,6 @@ type Client struct {
4440 token string
4541 userAgent string
4642 client * http.Client
47-
48- maxRetries int
49- maxRetryDelay time.Duration
50- onRetry OnRetryFunc
5143}
5244
5345// ClientOption is a function that modifies a Client
@@ -74,30 +66,6 @@ func WithHTTPClient(client *http.Client) ClientOption {
7466 }
7567}
7668
77- // WithMaxRetries sets the maximum number of retries for rate-limited requests.
78- func WithMaxRetries (n int ) ClientOption {
79- return func (c * Client ) {
80- c .maxRetries = n
81- }
82- }
83-
84- // WithMaxRetryDelay sets the maximum delay between retries
85- func WithMaxRetryDelay (d time.Duration ) ClientOption {
86- return func (c * Client ) {
87- c .maxRetryDelay = d
88- }
89- }
90-
91- // WithOnRetry sets a callback that is invoked before each retry sleep.
92- func WithOnRetry (f OnRetryFunc ) ClientOption {
93- return func (c * Client ) {
94- c .onRetry = f
95- }
96- }
97-
98- // OnRetryFunc is called before each retry sleep with the attempt number and delay duration.
99- type OnRetryFunc func (attempt int , delay time.Duration )
100-
10169// NewClient creates a new HTTP client with the given token and options
10270func NewClient (token string , opts ... ClientOption ) * Client {
10371 c := & Client {
@@ -164,23 +132,6 @@ func (e *ErrorResponse) IsTooManyRequests() bool {
164132 return e .StatusCode == http .StatusTooManyRequests
165133}
166134
167- // RetryAfter returns the duration to wait before retrying, based on the RateLimit-Reset header.
168- // Returns 0 if the header is missing or invalid.
169- func (e * ErrorResponse ) RetryAfter () time.Duration {
170- if e .Headers == nil {
171- return 0
172- }
173- resetStr := e .Headers .Get ("RateLimit-Reset" )
174- if resetStr == "" {
175- return 0
176- }
177- seconds , err := strconv .Atoi (resetStr )
178- if err != nil || seconds < 0 {
179- return 0
180- }
181- return time .Duration (seconds ) * time .Second
182- }
183-
184135// Do performs an HTTP request with the given method, endpoint, and body.
185136func (c * Client ) Do (ctx context.Context , method , endpoint string , body interface {}, v interface {}) error {
186137 // Ensure endpoint starts with "/"
@@ -215,21 +166,7 @@ func (c *Client) Do(ctx context.Context, method, endpoint string, body interface
215166 }
216167 }
217168
218- r := roko .NewRetrier (
219- roko .WithMaxAttempts (c .maxRetries + 1 ),
220- roko .WithStrategy (roko .Constant (0 )),
221- )
222-
223- respBody , err := roko .DoFunc (ctx , r , func (r * roko.Retrier ) ([]byte , error ) {
224- resp , err := c .send (ctx , method , reqURL , bodyBytes )
225- if err != nil {
226- if ! c .handleRetry (r , err ) {
227- r .Break ()
228- }
229- return nil , err
230- }
231- return resp , nil
232- })
169+ respBody , err := c .send (ctx , method , reqURL , bodyBytes )
233170 if err != nil {
234171 return err
235172 }
@@ -284,30 +221,3 @@ func (c *Client) send(ctx context.Context, method, reqURL string, body []byte) (
284221
285222 return respBody , nil
286223}
287-
288- // handleRetry checks if an error is retryable and configures the retrier accordingly.
289- // Returns true if the request should be retried, false otherwise.
290- func (c * Client ) handleRetry (r * roko.Retrier , err error ) bool {
291- errResp , ok := err .(* ErrorResponse )
292- if ! ok || ! errResp .IsTooManyRequests () {
293- return false
294- }
295-
296- attempt := r .AttemptCount ()
297- delay := errResp .RetryAfter ()
298- if attempt > 0 {
299- // Got rate-limited again means contention - back off exponentially
300- delay *= time .Duration (1 << attempt )
301- }
302-
303- if c .maxRetryDelay > 0 {
304- delay = min (delay , c .maxRetryDelay )
305- }
306-
307- if c .onRetry != nil {
308- c .onRetry (attempt , delay )
309- }
310-
311- r .SetNextInterval (delay )
312- return true
313- }
0 commit comments