blob: d7dfa2b24f3adae13374ff00837bdfb9b5e2ba73 [file] [log] [blame]
package gax
import (
"time"
"google.golang.org/grpc/codes"
)
type CallOption interface {
Resolve(*CallSettings)
}
type callOptions []CallOption
func (opts callOptions) Resolve(s *CallSettings) *CallSettings {
for _, opt := range opts {
opt.Resolve(s)
}
return s
}
// Encapsulates the call settings for a particular API call.
type CallSettings struct {
Timeout time.Duration
RetrySettings RetrySettings
}
// Per-call configurable settings for retrying upon transient failure.
type RetrySettings struct {
RetryCodes map[codes.Code]bool
BackoffSettings BackoffSettings
}
// Parameters to the exponential backoff algorithm for retrying.
type BackoffSettings struct {
DelayTimeoutSettings MultipliableDuration
RPCTimeoutSettings MultipliableDuration
TotalTimeout time.Duration
}
type MultipliableDuration struct {
Initial time.Duration
Max time.Duration
Multiplier float64
}
func (w CallSettings) Resolve(s *CallSettings) {
s.Timeout = w.Timeout
s.RetrySettings = w.RetrySettings
s.RetrySettings.RetryCodes = make(map[codes.Code]bool, len(w.RetrySettings.RetryCodes))
for key, value := range w.RetrySettings.RetryCodes {
s.RetrySettings.RetryCodes[key] = value
}
}
type withTimeout time.Duration
func (w withTimeout) Resolve(s *CallSettings) {
s.Timeout = time.Duration(w)
}
// WithTimeout sets the client-side timeout for API calls if the call isn't
// retrying.
func WithTimeout(timeout time.Duration) CallOption {
return withTimeout(timeout)
}
type withRetryCodes []codes.Code
func (w withRetryCodes) Resolve(s *CallSettings) {
s.RetrySettings.RetryCodes = make(map[codes.Code]bool)
for _, code := range []codes.Code(w) {
s.RetrySettings.RetryCodes[code] = true
}
}
// WithRetryCodes sets a list of Google API canonical error codes upon which a
// retry should be attempted. If nil, the call will not retry.
func WithRetryCodes(retryCodes []codes.Code) CallOption {
return withRetryCodes(retryCodes)
}
type withDelayTimeoutSettings MultipliableDuration
func (w withDelayTimeoutSettings) Resolve(s *CallSettings) {
s.RetrySettings.BackoffSettings.DelayTimeoutSettings = MultipliableDuration(w)
}
// WithDelayTimeoutSettings specifies:
// - The initial delay time, in milliseconds, between the completion of
// the first failed request and the initiation of the first retrying
// request.
// - The multiplier by which to increase the delay time between the
// completion of failed requests, and the initiation of the subsequent
// retrying request.
// - The maximum delay time, in milliseconds, between requests. When this
// value is reached, `RetryDelayMultiplier` will no longer be used to
// increase delay time.
func WithDelayTimeoutSettings(initial time.Duration, max time.Duration, multiplier float64) CallOption {
return withDelayTimeoutSettings(MultipliableDuration{initial, max, multiplier})
}
type withRPCTimeoutSettings MultipliableDuration
func (w withRPCTimeoutSettings) Resolve(s *CallSettings) {
s.RetrySettings.BackoffSettings.RPCTimeoutSettings = MultipliableDuration(w)
}
// WithRPCTimeoutSettings specifies:
// - The initial timeout parameter to the request.
// - The multiplier by which to increase the timeout parameter between
// failed requests.
// - The maximum timeout parameter, in milliseconds, for a request. When
// this value is reached, `RPCTimeoutMultiplier` will no longer be used
// to increase the timeout.
func WithRPCTimeoutSettings(initial time.Duration, max time.Duration, multiplier float64) CallOption {
return withRPCTimeoutSettings(MultipliableDuration{initial, max, multiplier})
}
type withTotalRetryTimeout time.Duration
func (w withTotalRetryTimeout) Resolve(s *CallSettings) {
s.RetrySettings.BackoffSettings.TotalTimeout = time.Duration(w)
}
// WithTotalRetryTimeout sets the total time, in milliseconds, starting from
// when the initial request is sent, after which an error will be returned
// regardless of the retrying attempts made meanwhile.
func WithTotalRetryTimeout(totalRetryTimeout time.Duration) CallOption {
return withTotalRetryTimeout(totalRetryTimeout)
}