]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
8d369c1b8c54a78013af8bddae3c94856a71c9cd
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / aws / aws-sdk-go / aws / request / retryer.go
1 package request
2
3 import (
4 "time"
5
6 "github.com/aws/aws-sdk-go/aws"
7 "github.com/aws/aws-sdk-go/aws/awserr"
8 )
9
10 // Retryer is an interface to control retry logic for a given service.
11 // The default implementation used by most services is the service.DefaultRetryer
12 // structure, which contains basic retry logic using exponential backoff.
13 type Retryer interface {
14 RetryRules(*Request) time.Duration
15 ShouldRetry(*Request) bool
16 MaxRetries() int
17 }
18
19 // WithRetryer sets a config Retryer value to the given Config returning it
20 // for chaining.
21 func WithRetryer(cfg *aws.Config, retryer Retryer) *aws.Config {
22 cfg.Retryer = retryer
23 return cfg
24 }
25
26 // retryableCodes is a collection of service response codes which are retry-able
27 // without any further action.
28 var retryableCodes = map[string]struct{}{
29 "RequestError": {},
30 "RequestTimeout": {},
31 ErrCodeResponseTimeout: {},
32 "RequestTimeoutException": {}, // Glacier's flavor of RequestTimeout
33 }
34
35 var throttleCodes = map[string]struct{}{
36 "ProvisionedThroughputExceededException": {},
37 "Throttling": {},
38 "ThrottlingException": {},
39 "RequestLimitExceeded": {},
40 "RequestThrottled": {},
41 "TooManyRequestsException": {}, // Lambda functions
42 "PriorRequestNotComplete": {}, // Route53
43 }
44
45 // credsExpiredCodes is a collection of error codes which signify the credentials
46 // need to be refreshed. Expired tokens require refreshing of credentials, and
47 // resigning before the request can be retried.
48 var credsExpiredCodes = map[string]struct{}{
49 "ExpiredToken": {},
50 "ExpiredTokenException": {},
51 "RequestExpired": {}, // EC2 Only
52 }
53
54 func isCodeThrottle(code string) bool {
55 _, ok := throttleCodes[code]
56 return ok
57 }
58
59 func isCodeRetryable(code string) bool {
60 if _, ok := retryableCodes[code]; ok {
61 return true
62 }
63
64 return isCodeExpiredCreds(code)
65 }
66
67 func isCodeExpiredCreds(code string) bool {
68 _, ok := credsExpiredCodes[code]
69 return ok
70 }
71
72 var validParentCodes = map[string]struct{}{
73 ErrCodeSerialization: struct{}{},
74 ErrCodeRead: struct{}{},
75 }
76
77 type temporaryError interface {
78 Temporary() bool
79 }
80
81 func isNestedErrorRetryable(parentErr awserr.Error) bool {
82 if parentErr == nil {
83 return false
84 }
85
86 if _, ok := validParentCodes[parentErr.Code()]; !ok {
87 return false
88 }
89
90 err := parentErr.OrigErr()
91 if err == nil {
92 return false
93 }
94
95 if aerr, ok := err.(awserr.Error); ok {
96 return isCodeRetryable(aerr.Code())
97 }
98
99 if t, ok := err.(temporaryError); ok {
100 return t.Temporary()
101 }
102
103 return isErrConnectionReset(err)
104 }
105
106 // IsErrorRetryable returns whether the error is retryable, based on its Code.
107 // Returns false if error is nil.
108 func IsErrorRetryable(err error) bool {
109 if err != nil {
110 if aerr, ok := err.(awserr.Error); ok {
111 return isCodeRetryable(aerr.Code()) || isNestedErrorRetryable(aerr)
112 }
113 }
114 return false
115 }
116
117 // IsErrorThrottle returns whether the error is to be throttled based on its code.
118 // Returns false if error is nil.
119 func IsErrorThrottle(err error) bool {
120 if err != nil {
121 if aerr, ok := err.(awserr.Error); ok {
122 return isCodeThrottle(aerr.Code())
123 }
124 }
125 return false
126 }
127
128 // IsErrorExpiredCreds returns whether the error code is a credential expiry error.
129 // Returns false if error is nil.
130 func IsErrorExpiredCreds(err error) bool {
131 if err != nil {
132 if aerr, ok := err.(awserr.Error); ok {
133 return isCodeExpiredCreds(aerr.Code())
134 }
135 }
136 return false
137 }
138
139 // IsErrorRetryable returns whether the error is retryable, based on its Code.
140 // Returns false if the request has no Error set.
141 //
142 // Alias for the utility function IsErrorRetryable
143 func (r *Request) IsErrorRetryable() bool {
144 return IsErrorRetryable(r.Error)
145 }
146
147 // IsErrorThrottle returns whether the error is to be throttled based on its code.
148 // Returns false if the request has no Error set
149 //
150 // Alias for the utility function IsErrorThrottle
151 func (r *Request) IsErrorThrottle() bool {
152 return IsErrorThrottle(r.Error)
153 }
154
155 // IsErrorExpired returns whether the error code is a credential expiry error.
156 // Returns false if the request has no Error set.
157 //
158 // Alias for the utility function IsErrorExpiredCreds
159 func (r *Request) IsErrorExpired() bool {
160 return IsErrorExpiredCreds(r.Error)
161 }