7 "github.com/aws/aws-sdk-go/aws/request"
8 "github.com/aws/aws-sdk-go/internal/sdkrand"
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:
17 // type retryer struct {
18 // client.DefaultRetryer
21 // // This implementation always has 100 max retries
22 // func (d retryer) MaxRetries() int { return 100 }
23 type DefaultRetryer struct {
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
33 // RetryRules returns the delay duration before retrying this request again
34 func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
35 // Set the upper limit of delay in retrying at ~five minutes
37 throttle := d.shouldThrottle(r)
39 if delay, ok := getRetryDelay(r); ok {
46 retryCount := r.RetryCount
47 if throttle && retryCount > 8 {
49 } else if retryCount > 13 {
53 delay := (1 << uint(retryCount)) * (sdkrand.SeededRand.Intn(minTime) + minTime)
54 return time.Duration(delay) * time.Millisecond
57 // ShouldRetry returns true if the request should be retried.
58 func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
59 // If one of the other handlers already set the retry state
60 // we don't want to override it based on the service's state
61 if r.Retryable != nil {
65 if r.HTTPResponse.StatusCode >= 500 && r.HTTPResponse.StatusCode != 501 {
68 return r.IsErrorRetryable() || d.shouldThrottle(r)
71 // ShouldThrottle returns true if the request should be throttled.
72 func (d DefaultRetryer) shouldThrottle(r *request.Request) bool {
73 switch r.HTTPResponse.StatusCode {
79 return r.IsErrorThrottle()
85 // This will look in the Retry-After header, RFC 7231, for how long
86 // it will wait before attempting another request
87 func getRetryDelay(r *request.Request) (time.Duration, bool) {
88 if !canUseRetryAfterHeader(r) {
92 delayStr := r.HTTPResponse.Header.Get("Retry-After")
93 if len(delayStr) == 0 {
97 delay, err := strconv.Atoi(delayStr)
102 return time.Duration(delay) * time.Second, true
105 // Will look at the status code to see if the retry header pertains to
107 func canUseRetryAfterHeader(r *request.Request) bool {
108 switch r.HTTPResponse.StatusCode {