src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

retryer.go (4856B)


      1 package aws
      2 
      3 import (
      4 	"context"
      5 	"fmt"
      6 	"time"
      7 )
      8 
      9 // RetryMode provides the mode the API client will use to create a retryer
     10 // based on.
     11 type RetryMode string
     12 
     13 const (
     14 	// RetryModeStandard model provides rate limited retry attempts with
     15 	// exponential backoff delay.
     16 	RetryModeStandard RetryMode = "standard"
     17 
     18 	// RetryModeAdaptive model provides attempt send rate limiting on throttle
     19 	// responses in addition to standard mode's retry rate limiting.
     20 	//
     21 	// Adaptive retry mode is experimental and is subject to change in the
     22 	// future.
     23 	RetryModeAdaptive RetryMode = "adaptive"
     24 )
     25 
     26 // ParseRetryMode attempts to parse a RetryMode from the given string.
     27 // Returning error if the value is not a known RetryMode.
     28 func ParseRetryMode(v string) (mode RetryMode, err error) {
     29 	switch v {
     30 	case "standard":
     31 		return RetryModeStandard, nil
     32 	case "adaptive":
     33 		return RetryModeAdaptive, nil
     34 	default:
     35 		return mode, fmt.Errorf("unknown RetryMode, %v", v)
     36 	}
     37 }
     38 
     39 func (m RetryMode) String() string { return string(m) }
     40 
     41 // Retryer is an interface to determine if a given error from a
     42 // attempt should be retried, and if so what backoff delay to apply. The
     43 // default implementation used by most services is the retry package's Standard
     44 // type. Which contains basic retry logic using exponential backoff.
     45 type Retryer interface {
     46 	// IsErrorRetryable returns if the failed attempt is retryable. This check
     47 	// should determine if the error can be retried, or if the error is
     48 	// terminal.
     49 	IsErrorRetryable(error) bool
     50 
     51 	// MaxAttempts returns the maximum number of attempts that can be made for
     52 	// an attempt before failing. A value of 0 implies that the attempt should
     53 	// be retried until it succeeds if the errors are retryable.
     54 	MaxAttempts() int
     55 
     56 	// RetryDelay returns the delay that should be used before retrying the
     57 	// attempt. Will return error if the delay could not be determined.
     58 	RetryDelay(attempt int, opErr error) (time.Duration, error)
     59 
     60 	// GetRetryToken attempts to deduct the retry cost from the retry token pool.
     61 	// Returning the token release function, or error.
     62 	GetRetryToken(ctx context.Context, opErr error) (releaseToken func(error) error, err error)
     63 
     64 	// GetInitialToken returns the initial attempt token that can increment the
     65 	// retry token pool if the attempt is successful.
     66 	GetInitialToken() (releaseToken func(error) error)
     67 }
     68 
     69 // RetryerV2 is an interface to determine if a given error from an attempt
     70 // should be retried, and if so what backoff delay to apply. The default
     71 // implementation used by most services is the retry package's Standard type.
     72 // Which contains basic retry logic using exponential backoff.
     73 //
     74 // RetryerV2 replaces the Retryer interface, deprecating the GetInitialToken
     75 // method in favor of GetAttemptToken which takes a context, and can return an error.
     76 //
     77 // The SDK's retry package's Attempt middleware, and utilities will always
     78 // wrap a Retryer as a RetryerV2. Delegating to GetInitialToken, only if
     79 // GetAttemptToken is not implemented.
     80 type RetryerV2 interface {
     81 	Retryer
     82 
     83 	// GetInitialToken returns the initial attempt token that can increment the
     84 	// retry token pool if the attempt is successful.
     85 	//
     86 	// Deprecated: This method does not provide a way to block using Context,
     87 	// nor can it return an error. Use RetryerV2, and GetAttemptToken instead.
     88 	GetInitialToken() (releaseToken func(error) error)
     89 
     90 	// GetAttemptToken returns the send token that can be used to rate limit
     91 	// attempt calls. Will be used by the SDK's retry package's Attempt
     92 	// middleware to get a send token prior to calling the temp and releasing
     93 	// the send token after the attempt has been made.
     94 	GetAttemptToken(context.Context) (func(error) error, error)
     95 }
     96 
     97 // NopRetryer provides a RequestRetryDecider implementation that will flag
     98 // all attempt errors as not retryable, with a max attempts of 1.
     99 type NopRetryer struct{}
    100 
    101 // IsErrorRetryable returns false for all error values.
    102 func (NopRetryer) IsErrorRetryable(error) bool { return false }
    103 
    104 // MaxAttempts always returns 1 for the original attempt.
    105 func (NopRetryer) MaxAttempts() int { return 1 }
    106 
    107 // RetryDelay is not valid for the NopRetryer. Will always return error.
    108 func (NopRetryer) RetryDelay(int, error) (time.Duration, error) {
    109 	return 0, fmt.Errorf("not retrying any attempt errors")
    110 }
    111 
    112 // GetRetryToken returns a stub function that does nothing.
    113 func (NopRetryer) GetRetryToken(context.Context, error) (func(error) error, error) {
    114 	return nopReleaseToken, nil
    115 }
    116 
    117 // GetInitialToken returns a stub function that does nothing.
    118 func (NopRetryer) GetInitialToken() func(error) error {
    119 	return nopReleaseToken
    120 }
    121 
    122 // GetAttemptToken returns a stub function that does nothing.
    123 func (NopRetryer) GetAttemptToken(context.Context) (func(error) error, error) {
    124 	return nopReleaseToken, nil
    125 }
    126 
    127 func nopReleaseToken(error) error { return nil }