| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- package client
- import (
- "math/rand"
- "sync"
- "time"
- "github.com/aws/aws-sdk-go/aws/request"
- )
- // DefaultRetryer implements basic retry logic using exponential backoff for
- // most services. If you want to implement custom retry logic, implement the
- // request.Retryer interface or create a structure type that composes this
- // struct and override the specific methods. For example, to override only
- // the MaxRetries method:
- //
- // type retryer struct {
- // client.DefaultRetryer
- // }
- //
- // // This implementation always has 100 max retries
- // func (d retryer) MaxRetries() int { return 100 }
- type DefaultRetryer struct {
- NumMaxRetries int
- }
- // MaxRetries returns the number of maximum returns the service will use to make
- // an individual API request.
- func (d DefaultRetryer) MaxRetries() int {
- return d.NumMaxRetries
- }
- var seededRand = rand.New(&lockedSource{src: rand.NewSource(time.Now().UnixNano())})
- // RetryRules returns the delay duration before retrying this request again
- func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
- // Set the upper limit of delay in retrying at ~five minutes
- minTime := 30
- throttle := d.shouldThrottle(r)
- if throttle {
- minTime = 500
- }
- retryCount := r.RetryCount
- if retryCount > 13 {
- retryCount = 13
- } else if throttle && retryCount > 8 {
- retryCount = 8
- }
- delay := (1 << uint(retryCount)) * (seededRand.Intn(minTime) + minTime)
- return time.Duration(delay) * time.Millisecond
- }
- // ShouldRetry returns true if the request should be retried.
- func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
- // If one of the other handlers already set the retry state
- // we don't want to override it based on the service's state
- if r.Retryable != nil {
- return *r.Retryable
- }
- if r.HTTPResponse.StatusCode >= 500 {
- return true
- }
- return r.IsErrorRetryable() || d.shouldThrottle(r)
- }
- // ShouldThrottle returns true if the request should be throttled.
- func (d DefaultRetryer) shouldThrottle(r *request.Request) bool {
- if r.HTTPResponse.StatusCode == 502 ||
- r.HTTPResponse.StatusCode == 503 ||
- r.HTTPResponse.StatusCode == 504 {
- return true
- }
- return r.IsErrorThrottle()
- }
- // lockedSource is a thread-safe implementation of rand.Source
- type lockedSource struct {
- lk sync.Mutex
- src rand.Source
- }
- func (r *lockedSource) Int63() (n int64) {
- r.lk.Lock()
- n = r.src.Int63()
- r.lk.Unlock()
- return
- }
- func (r *lockedSource) Seed(seed int64) {
- r.lk.Lock()
- r.src.Seed(seed)
- r.lk.Unlock()
- }
|