feat(httpclient)!: promote to v1.0.0 — retry-on-429 with Retry-After, DoJSONRequest, bump deps
Extend retry loop to handle HTTP 429 Too Many Requests: when the server includes a Retry-After header, that duration is used as the retry delay; otherwise falls back to the configured BackOffDelay. Add DoJSONRequest[Req, Resp] free function that serialises the request body as JSON, sets Content-Type, and delegates response decoding to DoJSON. Bump logz and xerrors from v0.9.0 to v1.0.0. API committed as stable.
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
retry "github.com/avast/retry-go/v4"
|
||||
@@ -91,6 +92,7 @@ func (c *httpClient) Do(req *http.Request) (*http.Response, error) {
|
||||
|
||||
result, err := c.cb.Execute(func() (any, error) {
|
||||
var innerErr error
|
||||
var retryAfterDelay time.Duration
|
||||
retryErr := retry.Do(
|
||||
func() error {
|
||||
if id := logz.GetRequestID(req.Context()); id != "" {
|
||||
@@ -110,6 +112,14 @@ func (c *httpClient) Do(req *http.Request) (*http.Response, error) {
|
||||
"status", resp.StatusCode,
|
||||
"latency", latency.String(),
|
||||
)
|
||||
if resp.StatusCode == http.StatusTooManyRequests {
|
||||
if ra := resp.Header.Get("Retry-After"); ra != "" {
|
||||
if secs, err := strconv.Atoi(ra); err == nil {
|
||||
retryAfterDelay = time.Duration(secs) * time.Second
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("rate limited: %d", resp.StatusCode)
|
||||
}
|
||||
if resp.StatusCode >= 500 {
|
||||
return fmt.Errorf("server error: %d", resp.StatusCode)
|
||||
}
|
||||
@@ -117,7 +127,14 @@ func (c *httpClient) Do(req *http.Request) (*http.Response, error) {
|
||||
},
|
||||
retry.Attempts(c.cfg.MaxRetries),
|
||||
retry.Delay(c.cfg.RetryDelay),
|
||||
retry.DelayType(retry.BackOffDelay),
|
||||
retry.DelayType(func(n uint, err error, config *retry.Config) time.Duration {
|
||||
if retryAfterDelay > 0 {
|
||||
d := retryAfterDelay
|
||||
retryAfterDelay = 0
|
||||
return d
|
||||
}
|
||||
return retry.BackOffDelay(n, err, config)
|
||||
}),
|
||||
retry.LastErrorOnly(true),
|
||||
)
|
||||
return resp, retryErr
|
||||
|
||||
Reference in New Issue
Block a user