]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
Initial transfer of provider code
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / aws / aws-sdk-go / aws / client / default_retryer.go
1 package client
2
3 import (
4 "math/rand"
5 "sync"
6 "time"
7
8 "github.com/aws/aws-sdk-go/aws/request"
9 )
10
11 // DefaultRetryer implements basic retry logic using exponential backoff for
12 // most services. If you want to implement custom retry logic, implement the
13 // request.Retryer interface or create a structure type that composes this
14 // struct and override the specific methods. For example, to override only
15 // the MaxRetries method:
16 //
17 // type retryer struct {
18 // service.DefaultRetryer
19 // }
20 //
21 // // This implementation always has 100 max retries
22 // func (d retryer) MaxRetries() uint { return 100 }
23 type DefaultRetryer struct {
24 NumMaxRetries int
25 }
26
27 // MaxRetries returns the number of maximum returns the service will use to make
28 // an individual API request.
29 func (d DefaultRetryer) MaxRetries() int {
30 return d.NumMaxRetries
31 }
32
33 var seededRand = rand.New(&lockedSource{src: rand.NewSource(time.Now().UnixNano())})
34
35 // RetryRules returns the delay duration before retrying this request again
36 func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
37 // Set the upper limit of delay in retrying at ~five minutes
38 minTime := 30
39 throttle := d.shouldThrottle(r)
40 if throttle {
41 minTime = 500
42 }
43
44 retryCount := r.RetryCount
45 if retryCount > 13 {
46 retryCount = 13
47 } else if throttle && retryCount > 8 {
48 retryCount = 8
49 }
50
51 delay := (1 << uint(retryCount)) * (seededRand.Intn(minTime) + minTime)
52 return time.Duration(delay) * time.Millisecond
53 }
54
55 // ShouldRetry returns true if the request should be retried.
56 func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
57 // If one of the other handlers already set the retry state
58 // we don't want to override it based on the service's state
59 if r.Retryable != nil {
60 return *r.Retryable
61 }
62
63 if r.HTTPResponse.StatusCode >= 500 {
64 return true
65 }
66 return r.IsErrorRetryable() || d.shouldThrottle(r)
67 }
68
69 // ShouldThrottle returns true if the request should be throttled.
70 func (d DefaultRetryer) shouldThrottle(r *request.Request) bool {
71 if r.HTTPResponse.StatusCode == 502 ||
72 r.HTTPResponse.StatusCode == 503 ||
73 r.HTTPResponse.StatusCode == 504 {
74 return true
75 }
76 return r.IsErrorThrottle()
77 }
78
79 // lockedSource is a thread-safe implementation of rand.Source
80 type lockedSource struct {
81 lk sync.Mutex
82 src rand.Source
83 }
84
85 func (r *lockedSource) Int63() (n int64) {
86 r.lk.Lock()
87 n = r.src.Int63()
88 r.lk.Unlock()
89 return
90 }
91
92 func (r *lockedSource) Seed(seed int64) {
93 r.lk.Lock()
94 r.src.Seed(seed)
95 r.lk.Unlock()
96 }