aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go')
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go80
1 files changed, 50 insertions, 30 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go b/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
index 1313478..a397b0d 100644
--- a/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
+++ b/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
@@ -1,11 +1,11 @@
1package client 1package client
2 2
3import ( 3import (
4 "math/rand" 4 "strconv"
5 "sync"
6 "time" 5 "time"
7 6
8 "github.com/aws/aws-sdk-go/aws/request" 7 "github.com/aws/aws-sdk-go/aws/request"
8 "github.com/aws/aws-sdk-go/internal/sdkrand"
9) 9)
10 10
11// DefaultRetryer implements basic retry logic using exponential backoff for 11// DefaultRetryer implements basic retry logic using exponential backoff for
@@ -15,11 +15,11 @@ import (
15// the MaxRetries method: 15// the MaxRetries method:
16// 16//
17// type retryer struct { 17// type retryer struct {
18// service.DefaultRetryer 18// client.DefaultRetryer
19// } 19// }
20// 20//
21// // This implementation always has 100 max retries 21// // This implementation always has 100 max retries
22// func (d retryer) MaxRetries() uint { return 100 } 22// func (d retryer) MaxRetries() int { return 100 }
23type DefaultRetryer struct { 23type DefaultRetryer struct {
24 NumMaxRetries int 24 NumMaxRetries int
25} 25}
@@ -30,25 +30,27 @@ func (d DefaultRetryer) MaxRetries() int {
30 return d.NumMaxRetries 30 return d.NumMaxRetries
31} 31}
32 32
33var seededRand = rand.New(&lockedSource{src: rand.NewSource(time.Now().UnixNano())})
34
35// RetryRules returns the delay duration before retrying this request again 33// RetryRules returns the delay duration before retrying this request again
36func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration { 34func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
37 // Set the upper limit of delay in retrying at ~five minutes 35 // Set the upper limit of delay in retrying at ~five minutes
38 minTime := 30 36 minTime := 30
39 throttle := d.shouldThrottle(r) 37 throttle := d.shouldThrottle(r)
40 if throttle { 38 if throttle {
39 if delay, ok := getRetryDelay(r); ok {
40 return delay
41 }
42
41 minTime = 500 43 minTime = 500
42 } 44 }
43 45
44 retryCount := r.RetryCount 46 retryCount := r.RetryCount
45 if retryCount > 13 { 47 if throttle && retryCount > 8 {
46 retryCount = 13
47 } else if throttle && retryCount > 8 {
48 retryCount = 8 48 retryCount = 8
49 } else if retryCount > 13 {
50 retryCount = 13
49 } 51 }
50 52
51 delay := (1 << uint(retryCount)) * (seededRand.Intn(minTime) + minTime) 53 delay := (1 << uint(retryCount)) * (sdkrand.SeededRand.Intn(minTime) + minTime)
52 return time.Duration(delay) * time.Millisecond 54 return time.Duration(delay) * time.Millisecond
53} 55}
54 56
@@ -60,7 +62,7 @@ func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
60 return *r.Retryable 62 return *r.Retryable
61 } 63 }
62 64
63 if r.HTTPResponse.StatusCode >= 500 { 65 if r.HTTPResponse.StatusCode >= 500 && r.HTTPResponse.StatusCode != 501 {
64 return true 66 return true
65 } 67 }
66 return r.IsErrorRetryable() || d.shouldThrottle(r) 68 return r.IsErrorRetryable() || d.shouldThrottle(r)
@@ -68,29 +70,47 @@ func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
68 70
69// ShouldThrottle returns true if the request should be throttled. 71// ShouldThrottle returns true if the request should be throttled.
70func (d DefaultRetryer) shouldThrottle(r *request.Request) bool { 72func (d DefaultRetryer) shouldThrottle(r *request.Request) bool {
71 if r.HTTPResponse.StatusCode == 502 || 73 switch r.HTTPResponse.StatusCode {
72 r.HTTPResponse.StatusCode == 503 || 74 case 429:
73 r.HTTPResponse.StatusCode == 504 { 75 case 502:
74 return true 76 case 503:
77 case 504:
78 default:
79 return r.IsErrorThrottle()
75 } 80 }
76 return r.IsErrorThrottle()
77}
78 81
79// lockedSource is a thread-safe implementation of rand.Source 82 return true
80type lockedSource struct {
81 lk sync.Mutex
82 src rand.Source
83} 83}
84 84
85func (r *lockedSource) Int63() (n int64) { 85// This will look in the Retry-After header, RFC 7231, for how long
86 r.lk.Lock() 86// it will wait before attempting another request
87 n = r.src.Int63() 87func getRetryDelay(r *request.Request) (time.Duration, bool) {
88 r.lk.Unlock() 88 if !canUseRetryAfterHeader(r) {
89 return 89 return 0, false
90 }
91
92 delayStr := r.HTTPResponse.Header.Get("Retry-After")
93 if len(delayStr) == 0 {
94 return 0, false
95 }
96
97 delay, err := strconv.Atoi(delayStr)
98 if err != nil {
99 return 0, false
100 }
101
102 return time.Duration(delay) * time.Second, true
90} 103}
91 104
92func (r *lockedSource) Seed(seed int64) { 105// Will look at the status code to see if the retry header pertains to
93 r.lk.Lock() 106// the status code.
94 r.src.Seed(seed) 107func canUseRetryAfterHeader(r *request.Request) bool {
95 r.lk.Unlock() 108 switch r.HTTPResponse.StatusCode {
109 case 429:
110 case 503:
111 default:
112 return false
113 }
114
115 return true
96} 116}