Add retry transport with configurable backoff and Retry-After support
Implements retry middleware as a RoundTripper wrapper: - Exponential and constant backoff strategies with jitter - RFC 7231 Retry-After header parsing (seconds and HTTP-date) - Default policy retries idempotent methods on 429/5xx and network errors - Body restoration via GetBody, context cancellation, response body cleanup
This commit is contained in:
56
retry/options.go
Normal file
56
retry/options.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package retry
|
||||
|
||||
import "time"
|
||||
|
||||
type options struct {
|
||||
maxAttempts int // default 3
|
||||
backoff Backoff // default ExponentialBackoff(100ms, 5s, true)
|
||||
policy Policy // default: defaultPolicy (retry on 5xx and network errors)
|
||||
retryAfter bool // default true, respect Retry-After header
|
||||
}
|
||||
|
||||
// Option configures the retry transport.
|
||||
type Option func(*options)
|
||||
|
||||
func defaults() options {
|
||||
return options{
|
||||
maxAttempts: 3,
|
||||
backoff: ExponentialBackoff(100*time.Millisecond, 5*time.Second, true),
|
||||
policy: defaultPolicy{},
|
||||
retryAfter: true,
|
||||
}
|
||||
}
|
||||
|
||||
// WithMaxAttempts sets the maximum number of attempts (including the first).
|
||||
// Values less than 1 are treated as 1 (no retries).
|
||||
func WithMaxAttempts(n int) Option {
|
||||
return func(o *options) {
|
||||
if n < 1 {
|
||||
n = 1
|
||||
}
|
||||
o.maxAttempts = n
|
||||
}
|
||||
}
|
||||
|
||||
// WithBackoff sets the backoff strategy used to compute delays between retries.
|
||||
func WithBackoff(b Backoff) Option {
|
||||
return func(o *options) {
|
||||
o.backoff = b
|
||||
}
|
||||
}
|
||||
|
||||
// WithPolicy sets the retry policy that decides whether to retry a request.
|
||||
func WithPolicy(p Policy) Option {
|
||||
return func(o *options) {
|
||||
o.policy = p
|
||||
}
|
||||
}
|
||||
|
||||
// WithRetryAfter controls whether the Retry-After response header is respected.
|
||||
// When enabled and present, the Retry-After delay is used if it exceeds the
|
||||
// backoff delay.
|
||||
func WithRetryAfter(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.retryAfter = enable
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user