mirror of
https://github.com/containers/skopeo.git
synced 2025-09-21 18:09:08 +00:00
Update module github.com/containers/common to v0.54.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
29
vendor/github.com/containers/common/pkg/retry/retry.go
generated
vendored
29
vendor/github.com/containers/common/pkg/retry/retry.go
generated
vendored
@@ -17,8 +17,9 @@ import (
|
||||
|
||||
// Options defines the option to retry.
|
||||
type Options struct {
|
||||
MaxRetry int // The number of times to possibly retry.
|
||||
Delay time.Duration // The delay to use between retries, if set.
|
||||
MaxRetry int // The number of times to possibly retry.
|
||||
Delay time.Duration // The delay to use between retries, if set.
|
||||
IsErrorRetryable func(error) bool
|
||||
}
|
||||
|
||||
// RetryOptions is deprecated, use Options.
|
||||
@@ -31,6 +32,12 @@ func RetryIfNecessary(ctx context.Context, operation func() error, options *Opti
|
||||
|
||||
// IfNecessary retries the operation in exponential backoff with the retry Options.
|
||||
func IfNecessary(ctx context.Context, operation func() error, options *Options) error {
|
||||
var isRetryable func(error) bool
|
||||
if options.IsErrorRetryable != nil {
|
||||
isRetryable = options.IsErrorRetryable
|
||||
} else {
|
||||
isRetryable = IsErrorRetryable
|
||||
}
|
||||
err := operation()
|
||||
for attempt := 0; err != nil && isRetryable(err) && attempt < options.MaxRetry; attempt++ {
|
||||
delay := time.Duration(int(math.Pow(2, float64(attempt)))) * time.Second
|
||||
@@ -49,7 +56,11 @@ func IfNecessary(ctx context.Context, operation func() error, options *Options)
|
||||
return err
|
||||
}
|
||||
|
||||
func isRetryable(err error) bool {
|
||||
// IsErrorRetryable makes a HEURISTIC determination whether it is worth retrying upon encountering an error.
|
||||
// That heuristic is NOT STABLE and it CAN CHANGE AT ANY TIME.
|
||||
// Callers that have a hard requirement for specific treatment of a class of errors should make their own check
|
||||
// instead of relying on this function maintaining its past behavior.
|
||||
func IsErrorRetryable(err error) bool {
|
||||
switch err {
|
||||
case nil:
|
||||
return false
|
||||
@@ -72,18 +83,18 @@ func isRetryable(err error) bool {
|
||||
}
|
||||
return true
|
||||
case *net.OpError:
|
||||
return isRetryable(e.Err)
|
||||
return IsErrorRetryable(e.Err)
|
||||
case *url.Error: // This includes errors returned by the net/http client.
|
||||
if e.Err == io.EOF { // Happens when a server accepts a HTTP connection and sends EOF
|
||||
return true
|
||||
}
|
||||
return isRetryable(e.Err)
|
||||
return IsErrorRetryable(e.Err)
|
||||
case syscall.Errno:
|
||||
return isErrnoRetryable(e)
|
||||
case errcode.Errors:
|
||||
// if this error is a group of errors, process them all in turn
|
||||
for i := range e {
|
||||
if !isRetryable(e[i]) {
|
||||
if !IsErrorRetryable(e[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -91,7 +102,7 @@ func isRetryable(err error) bool {
|
||||
case *multierror.Error:
|
||||
// if this error is a group of errors, process them all in turn
|
||||
for i := range e.Errors {
|
||||
if !isRetryable(e.Errors[i]) {
|
||||
if !IsErrorRetryable(e.Errors[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -102,11 +113,11 @@ func isRetryable(err error) bool {
|
||||
}
|
||||
if unwrappable, ok := e.(unwrapper); ok {
|
||||
err = unwrappable.Unwrap()
|
||||
return isRetryable(err)
|
||||
return IsErrorRetryable(err)
|
||||
}
|
||||
case unwrapper: // Test this last, because various error types might implement .Unwrap()
|
||||
err = e.Unwrap()
|
||||
return isRetryable(err)
|
||||
return IsErrorRetryable(err)
|
||||
}
|
||||
|
||||
return false
|
||||
|
Reference in New Issue
Block a user