1package aws
2
3import (
4 "context"
5 "fmt"
6 "time"
7)
8
9// RetryMode provides the mode the API client will use to create a retryer
10// based on.
11type RetryMode string
12
13const (
14 // RetryModeStandard model provides rate limited retry attempts with
15 // exponential backoff delay.
16 RetryModeStandard RetryMode = "standard"
17
18 // RetryModeAdaptive model provides attempt send rate limiting on throttle
19 // responses in addition to standard mode's retry rate limiting.
20 //
21 // Adaptive retry mode is experimental and is subject to change in the
22 // future.
23 RetryModeAdaptive RetryMode = "adaptive"
24)
25
26// ParseRetryMode attempts to parse a RetryMode from the given string.
27// Returning error if the value is not a known RetryMode.
28func ParseRetryMode(v string) (mode RetryMode, err error) {
29 switch v {
30 case "standard":
31 return RetryModeStandard, nil
32 case "adaptive":
33 return RetryModeAdaptive, nil
34 default:
35 return mode, fmt.Errorf("unknown RetryMode, %v", v)
36 }
37}
38
39func (m RetryMode) String() string { return string(m) }
40
41// Retryer is an interface to determine if a given error from a
42// attempt should be retried, and if so what backoff delay to apply. The
43// default implementation used by most services is the retry package's Standard
44// type. Which contains basic retry logic using exponential backoff.
45type Retryer interface {
46 // IsErrorRetryable returns if the failed attempt is retryable. This check
47 // should determine if the error can be retried, or if the error is
48 // terminal.
49 IsErrorRetryable(error) bool
50
51 // MaxAttempts returns the maximum number of attempts that can be made for
52 // an attempt before failing. A value of 0 implies that the attempt should
53 // be retried until it succeeds if the errors are retryable.
54 MaxAttempts() int
55
56 // RetryDelay returns the delay that should be used before retrying the
57 // attempt. Will return error if the delay could not be determined.
58 RetryDelay(attempt int, opErr error) (time.Duration, error)
59
60 // GetRetryToken attempts to deduct the retry cost from the retry token pool.
61 // Returning the token release function, or error.
62 GetRetryToken(ctx context.Context, opErr error) (releaseToken func(error) error, err error)
63
64 // GetInitialToken returns the initial attempt token that can increment the
65 // retry token pool if the attempt is successful.
66 GetInitialToken() (releaseToken func(error) error)
67}
68
69// RetryerV2 is an interface to determine if a given error from an attempt
70// should be retried, and if so what backoff delay to apply. The default
71// implementation used by most services is the retry package's Standard type.
72// Which contains basic retry logic using exponential backoff.
73//
74// RetryerV2 replaces the Retryer interface, deprecating the GetInitialToken
75// method in favor of GetAttemptToken which takes a context, and can return an error.
76//
77// The SDK's retry package's Attempt middleware, and utilities will always
78// wrap a Retryer as a RetryerV2. Delegating to GetInitialToken, only if
79// GetAttemptToken is not implemented.
80type RetryerV2 interface {
81 Retryer
82
83 // GetInitialToken returns the initial attempt token that can increment the
84 // retry token pool if the attempt is successful.
85 //
86 // Deprecated: This method does not provide a way to block using Context,
87 // nor can it return an error. Use RetryerV2, and GetAttemptToken instead.
88 GetInitialToken() (releaseToken func(error) error)
89
90 // GetAttemptToken returns the send token that can be used to rate limit
91 // attempt calls. Will be used by the SDK's retry package's Attempt
92 // middleware to get a send token prior to calling the temp and releasing
93 // the send token after the attempt has been made.
94 GetAttemptToken(context.Context) (func(error) error, error)
95}
96
97// NopRetryer provides a RequestRetryDecider implementation that will flag
98// all attempt errors as not retryable, with a max attempts of 1.
99type NopRetryer struct{}
100
101// IsErrorRetryable returns false for all error values.
102func (NopRetryer) IsErrorRetryable(error) bool { return false }
103
104// MaxAttempts always returns 1 for the original attempt.
105func (NopRetryer) MaxAttempts() int { return 1 }
106
107// RetryDelay is not valid for the NopRetryer. Will always return error.
108func (NopRetryer) RetryDelay(int, error) (time.Duration, error) {
109 return 0, fmt.Errorf("not retrying any attempt errors")
110}
111
112// GetRetryToken returns a stub function that does nothing.
113func (NopRetryer) GetRetryToken(context.Context, error) (func(error) error, error) {
114 return nopReleaseToken, nil
115}
116
117// GetInitialToken returns a stub function that does nothing.
118func (NopRetryer) GetInitialToken() func(error) error {
119 return nopReleaseToken
120}
121
122// GetAttemptToken returns a stub function that does nothing.
123func (NopRetryer) GetAttemptToken(context.Context) (func(error) error, error) {
124 return nopReleaseToken, nil
125}
126
127func nopReleaseToken(error) error { return nil }