Documentation
¶
Overview ¶
Package retry implements retry logic for HTTP clients.
The Client type can be used directly and instantiated with New.
client := New(Config{
Retries: 2,
Interval: 10 * time.Second,
}, nil) // uses http.DefaultClient
A Client can also be used as client middleware via its Then method.
client := New(Config{})
decorated := client.Then(new(http.Client))
Exponential backoff with jitter is also supported. For example:
client := New(Config{
Retries: 2,
Interval: 10 * time.Second,
Multiplier: 2.0,
Jitter: 0.2,
})
The basic formula for each time to wait before the next retry, in terms of Config fields, is:
Interval * (Multiplier^n) * randBetween[1-Jitter,1+Jitter]
where n is the 0-based retry.
See the documentation for the Config type for more details.
Deprecated: This functionality is moving to github.com/xmidt-org/retry
Index ¶
Examples ¶
Constants ¶
const ( // DefaultInterval is used when Config.Interval is nonpositive DefaultInterval time.Duration = 5 * time.Second )
Variables ¶
This section is empty.
Functions ¶
func DefaultCheck ¶
DefaultCheck is the Check predicate used if none is supplied.
This default implementation returns true under the following conditions:
- The response is not nil and the status code is one of: http.StatusRequestTimeout http.StatusTooManyRequests http.StatusGatewayTimeout
- The error is not nil and: supplies a "Temporary() bool" method that returns true (including any wrapped errors)
A consequence of honoring the Temporary() method on errors is that transient network errors will be retried. Examples of this include DNS errors that are marked as temporary.
In all other cases, this default function returns false. Importantly, this means that context.Canceled errors are not retryable errors when using this check function.
Types ¶
type Check ¶
Check is a predicate type used to determine if a result from http.Client.Do should be retried. Implementations should only return true if it is reasonable to retry the request. Examples of retryable situations are gateway timeouts and 429 (too many requests) responses.
For any HTTP transaction that is considered a success, implementations should return false to halt further retries.
For any HTTP transaction that failed but that shouldn't be retried, implementations should return false. An example of this is an HTTP status of 400, since that indicates that no further use of that request will succeed.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is an httpaux.Client that retries HTTP transactions. Instances can be used in (2) ways:
(1) Client.Do can execute HTTP transactions using whatever retry semantics were defined in New. If Config.Retries was nonpositive, the Client won't perform any retries.
(2) Client.Then can be used as client middleware to attach retry semantics to other HTTP clients.
Example (Defaults) ¶
client := New(Config{}, nil) // uses http.DefaultClient
fmt.Println(client.Retries())
Output: 0
Example (ExponentialBackoff) ¶
client := New(Config{
Retries: 5,
Interval: 3 * time.Minute,
Multiplier: 1.5,
// uses DefaultCheck
}, new(http.Client))
fmt.Println(client.Retries())
Output: 5
Example (ExponentialBackoffWithJitter) ¶
client := New(Config{
Retries: 5,
Interval: 3 * time.Minute,
Multiplier: 3.0,
// a random window that increases with each retry
// the window is [1-Jitter,1+Jitter], and a random
// value in that range is multiplied by Interval*Multipler^n
// where n is the 0-based attempt.
Jitter: 0.2,
}, new(http.Client))
fmt.Println(client.Retries())
Output: 5
Example (Middleware) ¶
retryClient := New(Config{
Retries: 3,
Interval: 1 * time.Minute,
}, nil) // will use http.DefaultClient
// this is a decorated client using the above retry semantics
_ = retryClient.Then(new(http.Client))
fmt.Println(retryClient.Retries())
Output: 3
Example (Simple) ¶
client := New(Config{
Retries: 2,
Interval: 3 * time.Minute,
// custom Check, if desired
Check: func(r *http.Response, err error) bool {
return err == nil && r.StatusCode != 200
},
}, new(http.Client))
fmt.Println(client.Retries())
Output: 2
func New ¶
New constructs a Client from a configuration. If cfg.Retries is nonpositive, the returned client will not do retries.
The next instance is used to actually execute HTTP transactions. If next is nil, http.DefaultClient is used.
func (*Client) Do ¶
Do takes in an original *http.Request and makes an initial attempt plus a maximum number of retries in order to satisfy the request.
For each request, a State instance is put into the request's context that allows decorated clients to access information about the current attempt. Decorated code can obtain this State with a call to GetState.
type Config ¶
type Config struct {
// Retries is the number of attempts to retry an HTTP transaction. This value
// does not include the initial attempt. The maximum number of HTTP transactions
// will be 1+Retries, accounting for the initial attempt.
//
// If this value is unset or nonpositive, no retries will be performed. Leaving this
// value unset will disable retries even if any other fields of this type are set.
Retries int `json:"retries" yaml:"retries"`
// Interval is the base duration between each retry attempt. If nonpositive, DefaultInterval
// is used.
//
// In the simple case, when Multiplier and Jitter are unset, this is the interval
// between each retry.
//
// If Multiplier is set to a positive value, typically greater than 1.0, then each
// successive retry waits an amount equal to Interval*(Multiplier^n), where n is
// the current 0-based retry. Although a Multiplier of less than 1.0 is allowed, it's discouraged
// since that means each retry waits less time than the previous retry.
//
// If a Jitter is set, then each retry's interval is multiplied by a random number
// in the range [1-Jitter,1+Jitter]. This is over and above any Multiplier value.
Interval time.Duration `json:"interval" yaml:"interval"`
// Multiplier is the factor applied to each retry interval. If nonpositive, no multiplier
// is used. There is no default for this field.
//
// Each retry's interval is computed by (Previous*Multiplier), not including Jitter.
// A Multiplier value of less than 1.0 will result in decreasing wait times for each retry.
Multiplier float64 `json:"multiplier" yaml:"multiplier"`
// Jitter is the factor used to determine random intervals. The actual interval
// between retries is generated by multiplying by a random number in the range
// [1-Jitter, 1+Jitter]. That is, the Jitter is a percentage above and below the
// base interval.
//
// If this field is not in the open range (0.0, 1.0), no jitter is used.
Jitter float64 `json:"jitter" yaml:"jitter"`
// Random is the optional source of randomness used in computing jitter.
// If this value is omitted, math/rand.New is used to compute a source
// of randomness with the current time as the seed.
Random Random `json:"-" yaml:"-"`
// Timer is the timer strategy used to creating channels for awaiting
// until the next retry interval. If unset, DefaultTimer is used.
Timer Timer `json:"-" yaml:"-"`
// Check is the predicate used to determine if the result of http.Client.Do
// can be retried. Even if this predicate returns true, the number of Retries
// will not be exceeded.
Check Check `json:"-" yaml:"-"`
}
Config is the set of configuration options for an HTTP client retry decorator
type GetBodyError ¶
type GetBodyError struct {
// Err is the error returned from GetBody
Err error
}
GetBodyError indicates that http.Request.GetBody returned an error. Retries cannot continue in this case, since the original request body is unavailable.
A request may not have GetBody set. In that case, a Client will not attempt to refresh the body before each retry.
func (*GetBodyError) Error ¶
func (err *GetBodyError) Error() string
Error fulfills the error interface.
func (*GetBodyError) Unwrap ¶ added in v0.1.3
func (err *GetBodyError) Unwrap() error
Unwrap returns the actual error returned from GetBody.
type Random ¶
Random is the subset of rand.Rand methods used by this package to compute jitter. *rand.Rand implements this interface.
type RandomFunc ¶ added in v0.1.3
RandomFunc is a closure type that implements Random.
func (RandomFunc) Int63n ¶ added in v0.1.3
func (rf RandomFunc) Int63n(v int64) int64
Int63n satisfies the Random interface.
type State ¶
type State struct {
// contains filtered or unexported fields
}
State is the current state of a retry operation. Instances of this type are available in request context's during the initial attempt and any retries.
This type is never safe for concurrent access.
func GetState ¶
GetState returns the retry State associated with the given context. Decorated code can make use of this for metrics, logging, etc.
IMPORTANT: State is not safe for concurrent access. The State instance returned by this function should never be retained.
func (*State) Attempt ¶
Attempt is the 0-based attempt to execute this HTTP transaction. Zero (0) means the initial attempt. Positive values indicate the retry attempt. In other words, this method returns the number of attempts that have been tried previously.