this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Tell RobustHTTPClient to treat rate-limiting as non-retryable error (#439)

This is a simplest possible approach to pass through hitting a rate
limit to the application that uses the default XRPC client.

It's a design question if this is what you want to have. Alternatives
include:
* Gate this behaviour change behind a flag in `xrpc.Client` struct
* Allowing to specify a threshold for the duration until rate limit
reset, below which the client would keep the current behaviour

FWIW, JS client seems to not have any retry logic in place.

authored by

Jaz and committed by
GitHub
7a3aad7e 1b8971c9

+15 -5
+15 -3
util/http.go
··· 1 1 package util 2 2 3 3 import ( 4 + "context" 4 5 "net/http" 5 6 "time" 6 7 ··· 35 36 // timeouts and retries. The returned client has the stdlib http.Client 36 37 // interface, but has Hashicorp retryablehttp logic internally. 37 38 // 38 - // This client will retry on connection errors, 5xx status (except 501), and 39 - // 429 Backoff requests (respecting 'Retry-After' header). It will log 40 - // intermediate failures with WARN level. This does not start from 39 + // This client will retry on connection errors, 5xx status (except 501). 40 + // It will log intermediate failures with WARN level. This does not start from 41 41 // http.DefaultClient. 42 42 // 43 43 // This should be usable for XRPC clients, and other general inter-service ··· 50 50 retryClient.RetryWaitMin = 1 * time.Second 51 51 retryClient.RetryWaitMax = 10 * time.Second 52 52 retryClient.Logger = retryablehttp.LeveledLogger(LeveledZap{log}) 53 + retryClient.CheckRetry = XRPCRetryPolicy 53 54 client := retryClient.StandardClient() 54 55 client.Timeout = 30 * time.Second 55 56 return client ··· 62 63 client.Timeout = 1 * time.Second 63 64 return client 64 65 } 66 + 67 + // XRPCRetryPolicy is a custom wrapper around retryablehttp.DefaultRetryPolicy. 68 + // It treats `429 Too Many Requests` as non-retryable, so the application can decide 69 + // how to deal with rate-limiting. 70 + func XRPCRetryPolicy(ctx context.Context, resp *http.Response, err error) (bool, error) { 71 + if err == nil && resp.StatusCode == http.StatusTooManyRequests { 72 + return false, nil 73 + } 74 + // TODO: implement returning errors on non-200 responses w/o introducing circular dependencies. 75 + return retryablehttp.DefaultRetryPolicy(ctx, resp, err) 76 + }
-2
xrpc/xrpc.go
··· 19 19 20 20 type Client struct { 21 21 // Client is an HTTP client to use. If not set, defaults to http.RobustHTTPClient(). 22 - // Note that http.RobustHTTPClient() swallows retryable errors (including hitting a rate limit), 23 - // not allowing your code to handle them differently. 24 22 Client *http.Client 25 23 Auth *AuthInfo 26 24 AdminToken *string