Documentation
¶
Overview ¶
Package call provides a resilient HTTP client with retry, circuit breaker, and timeout support using a composable builder pattern.
Index ¶
- Variables
- func ParseRetryAfter(value string, now time.Time) time.Duration
- func RemoveBreaker(name string)
- type Breaker
- type CachedToken
- type CircuitBreaker
- type Client
- type Option
- func WithBreaker(b Breaker) Option
- func WithCircuitBreaker(name string, threshold int, resetTimeout time.Duration) Option
- func WithHTTPClient(hc *http.Client) Option
- func WithIdempotentOnlyRetries() Option
- func WithRetry(maxAttempts int, baseDelay time.Duration) Option
- func WithRetryPolicy(policy RetryPolicy) Option
- func WithTimeout(d time.Duration) Option
- func WithTokenSource(source TokenSource) Option
- type Retrier
- type RetryContext
- type RetryDecision
- type RetryPolicy
- type State
- type TokenOption
- type TokenSource
Constants ¶
This section is empty.
Variables ¶
var ErrBodyNotRewindable = errors.New("call: request body is not rewindable")
ErrBodyNotRewindable is returned when a retry would need to resend a request body that cannot be recreated through Request.GetBody.
var ErrCircuitOpen = errors.New("circuit breaker is open")
ErrCircuitOpen is returned when a circuit breaker is in the Open state and rejects requests.
Functions ¶
func ParseRetryAfter ¶ added in v11.3.24
ParseRetryAfter parses an RFC 9110 Retry-After header as seconds or HTTP-date.
func RemoveBreaker ¶
func RemoveBreaker(name string)
RemoveBreaker removes a named circuit breaker from the global registry, allowing its memory to be reclaimed. Safe to call even if the name does not exist. Use this when a downstream service is decommissioned or when breaker names contain dynamic data.
Types ¶
type Breaker ¶
type Breaker interface {
// Allow checks whether a request may proceed. Returns ErrCircuitOpen
// (or similar) when the circuit is open.
Allow() error
// Record reports the outcome of a request so the breaker can update state.
Record(success bool)
}
Breaker defines the circuit breaker behavior. Consumers can provide their own implementation (e.g., wrapping sony/gobreaker) via WithBreaker.
type CachedToken ¶
type CachedToken struct {
// contains filtered or unexported fields
}
CachedToken caches a token and refreshes it when within Leeway of expiry.
func NewCachedToken ¶
func NewCachedToken(fetchFn func(ctx context.Context) (string, time.Time, error), opts ...TokenOption) *CachedToken
NewCachedToken creates a TokenSource that caches tokens from fetchFn.
type CircuitBreaker ¶
type CircuitBreaker struct {
// contains filtered or unexported fields
}
CircuitBreaker implements the circuit breaker pattern. It tracks consecutive failures and short-circuits requests when the failure threshold is reached, giving the downstream service time to recover.
func GetBreaker ¶
func GetBreaker(name string, threshold int, resetTimeout time.Duration) *CircuitBreaker
GetBreaker returns an existing circuit breaker for the given name or creates a new one with the provided threshold and reset timeout. Breakers are singletons keyed by name.
func (*CircuitBreaker) Allow ¶
func (cb *CircuitBreaker) Allow() error
Allow checks whether a request is permitted through the breaker. It returns nil when the request may proceed or ErrCircuitOpen when it must be rejected.
func (*CircuitBreaker) Record ¶
func (cb *CircuitBreaker) Record(success bool)
Record reports the outcome of a request to the breaker so it can update its internal state accordingly.
func (*CircuitBreaker) State ¶
func (cb *CircuitBreaker) State() State
State returns the current state of the circuit breaker. The internal probing state is reported as StateHalfOpen to external consumers.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a resilient HTTP client that wraps the standard http.Client with optional retry, circuit breaker, and timeout middleware. Construct one using New with functional options.
func New ¶
New creates a Client with the given options applied. Without options it behaves like a default http.Client with a 30-second timeout.
func (*Client) Batch ¶
func (c *Client) Batch(ctx context.Context, requests []*http.Request, opts ...work.Option) ([]*http.Response, error)
Batch executes multiple requests concurrently with bounded concurrency using work.Map. Results are returned in the same order as the input requests.
func (*Client) Do ¶
Do executes an HTTP request with all configured middleware applied. The middleware order is: circuit breaker check, retry loop, execute.
If the request does not carry a context, one is created with the configured timeout. If a context is already present its deadline is respected.
type Option ¶
type Option func(*Client)
Option configures a Client.
func WithBreaker ¶
WithBreaker sets a custom circuit breaker implementation.
func WithCircuitBreaker ¶
WithCircuitBreaker protects the client with a named circuit breaker that opens after threshold consecutive failures and resets after resetTimeout.
func WithHTTPClient ¶
WithHTTPClient replaces the underlying *http.Client used by the call Client. This is useful when you need a custom Transport (e.g., proxy routing, SSRF-safe dialer) or a custom CheckRedirect policy. The timeout set by WithTimeout is applied via a per-request context and does not override the http.Client.Timeout field — set that to zero or remove it if you want the call-level timeout to be authoritative.
func WithIdempotentOnlyRetries ¶ added in v11.3.24
func WithIdempotentOnlyRetries() Option
WithIdempotentOnlyRetries suppresses retries for non-idempotent HTTP methods. It is opt-in so existing WithRetry behavior remains backward compatible.
func WithRetry ¶
WithRetry enables the historical method-agnostic retries for transient (5xx) errors using exponential backoff with jitter. MaxAttempts is clamped to a minimum of 1. This option can retry mutation methods such as POST; callers must ensure those operations are duplicate-safe or also apply WithIdempotentOnlyRetries.
Note: retries re-send the same *http.Request. Requests with a non-nil Body must be rewindable through Request.GetBody. If a retry is required and the body cannot be recreated, Do returns ErrBodyNotRewindable instead of sending an empty or partially consumed body. Requests with nil Body (GET, DELETE, HEAD) are always safe to retry.
func WithRetryPolicy ¶ added in v11.3.24
func WithRetryPolicy(policy RetryPolicy) Option
WithRetryPolicy configures a custom retry policy. If retries were not already enabled, it enables a default 3-attempt retrier with the provided policy.
func WithTimeout ¶
WithTimeout sets the maximum duration for a single HTTP request attempt.
func WithTokenSource ¶
func WithTokenSource(source TokenSource) Option
WithTokenSource configures a TokenSource that provides a Bearer token injected into the Authorization header of every outbound request.
type Retrier ¶
type Retrier struct {
MaxAttempts int
BaseDelay time.Duration
Policy RetryPolicy
IdempotentOnly bool
// contains filtered or unexported fields
}
Retrier provides retry logic with exponential backoff and jitter for transient server errors (5xx). It never retries client errors (4xx) unless an explicit Retry-After header on 429 provides retry guidance.
func (*Retrier) Do ¶
func (r *Retrier) Do(ctx context.Context, fn func() (*http.Response, error)) (*http.Response, error)
Do executes fn up to MaxAttempts times. The default policy preserves the historical behavior: network errors and 5xx responses retry with backoff. It additionally honors explicit Retry-After guidance on 429/503 responses. It respects context cancellation and deadline, stopping immediately when the context is done.
If the request has a GetBody function, it is called before each retry to rewind the request body. Requests with a body but no working GetBody fail with ErrBodyNotRewindable instead of sending an empty/consumed body.
type RetryContext ¶ added in v11.3.24
RetryContext describes a completed attempt for retry policy decisions.
type RetryDecision ¶ added in v11.3.24
RetryDecision is returned by RetryPolicy.
func DefaultRetryPolicy ¶ added in v11.3.24
func DefaultRetryPolicy(rc RetryContext) RetryDecision
DefaultRetryPolicy preserves historical defaults: retry network errors and 5xx responses with exponential backoff. It additionally honors explicit Retry-After guidance on 429 and 503 responses without changing no-header 429 behavior.
type RetryPolicy ¶ added in v11.3.24
type RetryPolicy func(RetryContext) RetryDecision
RetryPolicy decides whether an attempt should be retried.
func IdempotentOnlyPolicy ¶ added in v11.3.24
func IdempotentOnlyPolicy(next RetryPolicy) RetryPolicy
IdempotentOnlyPolicy wraps a retry policy and suppresses retries for methods that are not idempotent by HTTP semantics.