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.
4.2 KiB
4.2 KiB
Changelog
All notable changes to this module will be documented in this file.
The format is based on Keep a Changelog, and this module adheres to Semantic Versioning.
1.0.0 — 2026-05-12
Added
DoJSONRequest[Req, Resp any](ctx, client, method, rawURL, body) (*Resp, error)— free generic function that serialisesbodyas JSON, constructs the*http.RequestwithContent-Type: application/json, and delegates response decoding toDoJSON. ComplementsDoJSONfor POST/PUT/PATCH calls; useDoJSONfor GET/DELETE where there is no request body.
Changed
- Retry loop now handles HTTP 429 Too Many Requests: a 429 response triggers a retry (previously only
>= 500did). When the server includes aRetry-Afterheader with an integer seconds value, that duration is used as the retry delay for that attempt; otherwise the configuredBackOffDelayapplies. logzandxerrorsdependencies bumped from v0.9.0 to v1.0.0.
Unchanged
All other API (Client, Config, DefaultConfig, New, NewWithDefaults, DoJSON,
MapStatusToError) is API-compatible with v0.9.0.
0.9.0 - 2026-03-18
Added
Clientinterface:Do(req *http.Request) (*http.Response, error).Configstruct: fieldsName,Timeout(default30s),DialTimeout(default5s),MaxRetries(default3),RetryDelay(default1s),CBThreshold(default10),CBTimeout(default1m); settable viaHTTP_*environment variables.DefaultConfig() Config: returns aConfigpopulated with all default values.New(logger logz.Logger, cfg Config) Client: constructs a client with agobreakercircuit breaker wrapping anavast/retry-goretry loop. The circuit breaker trips afterCBThresholdconsecutive failures and resets afterCBTimeout.NewWithDefaults(logger logz.Logger) Client: convenience constructor; equivalent toNew(logger, DefaultConfig()).- Retry behaviour: up to
MaxRetriesattempts with exponential backoff (retry.BackOffDelay). Only network errors and HTTP 5xx responses are retried; 4xx responses are not. - Circuit breaker behaviour: the breaker wraps the full retry sequence, so one fully-exhausted retry sequence counts as one failure. State transitions are logged at
Warnlevel withname,from, andtofields. - Request ID propagation:
logz.GetRequestID(ctx)is called on each attempt; if a request ID is present, it is forwarded as theX-Request-IDrequest header. - Per-request structured logging: successful requests emit an
Infolog withmethod,url,status, andlatencyfields; failed individual attempts emit aDebuglog. - Error mapping on
Do: open circuit →ErrUnavailable; post-retry HTTP error response →MapStatusToError; network/timeout error →ErrInternal. DoJSON[T any](ctx context.Context, client Client, req *http.Request) (*T, error): generic free function that executes a request and decodes the JSON response body intoT; returns*Ton success and a xerrors-typed error for network failures, HTTP 4xx/5xx responses, unreadable bodies, or JSON decode failures.MapStatusToError(code int, msg string) error(exported): maps HTTP status codes to xerrors codes —404→ErrNotFound,400→ErrInvalidInput,401→ErrUnauthorized,403→ErrPermissionDenied,409→ErrAlreadyExists,429→ErrUnavailable, all others →ErrInternal.- Dial timeout applied via a custom
net.Dialeron thehttp.Transport, independent of the per-requestTimeout.
Design Notes
- The circuit breaker wraps the retry loop rather than individual attempts; a full set of exhausted retries registers as a single failure against the breaker threshold, preventing overly aggressive tripping.
DoJSONis a free generic function rather than a method so it works with anyClientimplementation, including mocks, without requiring a concrete type.- The module has no lifecycle (no
OnInit/OnStart/OnStop) and does not depend onlauncherorhealth; it is a stateless constructor suitable for use at any tier.