mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-22 08:26:19 +01:00
87c77727e4
* lib/backup/s3remote: update AWS SDK to v2 * Update lib/backup/s3remote/s3.go Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com> * lib/backup/s3remote: refactor error handling Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
128 lines
4.7 KiB
Go
128 lines
4.7 KiB
Go
package aws
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// RetryMode provides the mode the API client will use to create a retryer
|
|
// based on.
|
|
type RetryMode string
|
|
|
|
const (
|
|
// RetryModeStandard model provides rate limited retry attempts with
|
|
// exponential backoff delay.
|
|
RetryModeStandard RetryMode = "standard"
|
|
|
|
// RetryModeAdaptive model provides attempt send rate limiting on throttle
|
|
// responses in addition to standard mode's retry rate limiting.
|
|
//
|
|
// Adaptive retry mode is experimental and is subject to change in the
|
|
// future.
|
|
RetryModeAdaptive RetryMode = "adaptive"
|
|
)
|
|
|
|
// ParseRetryMode attempts to parse a RetryMode from the given string.
|
|
// Returning error if the value is not a known RetryMode.
|
|
func ParseRetryMode(v string) (mode RetryMode, err error) {
|
|
switch v {
|
|
case "standard":
|
|
return RetryModeStandard, nil
|
|
case "adaptive":
|
|
return RetryModeAdaptive, nil
|
|
default:
|
|
return mode, fmt.Errorf("unknown RetryMode, %v", v)
|
|
}
|
|
}
|
|
|
|
func (m RetryMode) String() string { return string(m) }
|
|
|
|
// Retryer is an interface to determine if a given error from a
|
|
// attempt should be retried, and if so what backoff delay to apply. The
|
|
// default implementation used by most services is the retry package's Standard
|
|
// type. Which contains basic retry logic using exponential backoff.
|
|
type Retryer interface {
|
|
// IsErrorRetryable returns if the failed attempt is retryable. This check
|
|
// should determine if the error can be retried, or if the error is
|
|
// terminal.
|
|
IsErrorRetryable(error) bool
|
|
|
|
// MaxAttempts returns the maximum number of attempts that can be made for
|
|
// an attempt before failing. A value of 0 implies that the attempt should
|
|
// be retried until it succeeds if the errors are retryable.
|
|
MaxAttempts() int
|
|
|
|
// RetryDelay returns the delay that should be used before retrying the
|
|
// attempt. Will return error if the if the delay could not be determined.
|
|
RetryDelay(attempt int, opErr error) (time.Duration, error)
|
|
|
|
// GetRetryToken attempts to deduct the retry cost from the retry token pool.
|
|
// Returning the token release function, or error.
|
|
GetRetryToken(ctx context.Context, opErr error) (releaseToken func(error) error, err error)
|
|
|
|
// GetInitialToken returns the initial attempt token that can increment the
|
|
// retry token pool if the attempt is successful.
|
|
GetInitialToken() (releaseToken func(error) error)
|
|
}
|
|
|
|
// RetryerV2 is an interface to determine if a given error from an attempt
|
|
// should be retried, and if so what backoff delay to apply. The default
|
|
// implementation used by most services is the retry package's Standard type.
|
|
// Which contains basic retry logic using exponential backoff.
|
|
//
|
|
// RetryerV2 replaces the Retryer interface, deprecating the GetInitialToken
|
|
// method in favor of GetAttemptToken which takes a context, and can return an error.
|
|
//
|
|
// The SDK's retry package's Attempt middleware, and utilities will always
|
|
// wrap a Retryer as a RetryerV2. Delegating to GetInitialToken, only if
|
|
// GetAttemptToken is not implemented.
|
|
type RetryerV2 interface {
|
|
Retryer
|
|
|
|
// GetInitialToken returns the initial attempt token that can increment the
|
|
// retry token pool if the attempt is successful.
|
|
//
|
|
// Deprecated: This method does not provide a way to block using Context,
|
|
// nor can it return an error. Use RetryerV2, and GetAttemptToken instead.
|
|
GetInitialToken() (releaseToken func(error) error)
|
|
|
|
// GetAttemptToken returns the send token that can be used to rate limit
|
|
// attempt calls. Will be used by the SDK's retry package's Attempt
|
|
// middleware to get a send token prior to calling the temp and releasing
|
|
// the send token after the attempt has been made.
|
|
GetAttemptToken(context.Context) (func(error) error, error)
|
|
}
|
|
|
|
// NopRetryer provides a RequestRetryDecider implementation that will flag
|
|
// all attempt errors as not retryable, with a max attempts of 1.
|
|
type NopRetryer struct{}
|
|
|
|
// IsErrorRetryable returns false for all error values.
|
|
func (NopRetryer) IsErrorRetryable(error) bool { return false }
|
|
|
|
// MaxAttempts always returns 1 for the original attempt.
|
|
func (NopRetryer) MaxAttempts() int { return 1 }
|
|
|
|
// RetryDelay is not valid for the NopRetryer. Will always return error.
|
|
func (NopRetryer) RetryDelay(int, error) (time.Duration, error) {
|
|
return 0, fmt.Errorf("not retrying any attempt errors")
|
|
}
|
|
|
|
// GetRetryToken returns a stub function that does nothing.
|
|
func (NopRetryer) GetRetryToken(context.Context, error) (func(error) error, error) {
|
|
return nopReleaseToken, nil
|
|
}
|
|
|
|
// GetInitialToken returns a stub function that does nothing.
|
|
func (NopRetryer) GetInitialToken() func(error) error {
|
|
return nopReleaseToken
|
|
}
|
|
|
|
// GetAttemptToken returns a stub function that does nothing.
|
|
func (NopRetryer) GetAttemptToken(context.Context) (func(error) error, error) {
|
|
return nopReleaseToken, nil
|
|
}
|
|
|
|
func nopReleaseToken(error) error { return nil }
|