impl: add a retry with result function (#2837)
* impl: add a retry with result function * fix ci errs
This commit is contained in:
parent
06b7c1de93
commit
5133ad83b1
|
|
@ -20,6 +20,7 @@ import (
|
|||
"crypto/md5"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
|
|
@ -197,6 +198,26 @@ func Retry(operation retryFunc, retryCount int, initialDelayMilliseconds int) er
|
|||
return err
|
||||
}
|
||||
|
||||
// Retry retries an operation with a return value
|
||||
func RetryWithResult[T any](operation func() (T, error), retryCount int, initialDelayMilliseconds int) (result T, err error) {
|
||||
result, err = operation()
|
||||
if err == nil {
|
||||
return result, nil
|
||||
}
|
||||
for i := 0; i < retryCount; i++ {
|
||||
sleepDuration := time.Millisecond * time.Duration(int(math.Pow(2, float64(i)))*initialDelayMilliseconds)
|
||||
logrus.Warnf("Retrying operation after %s due to %v", sleepDuration, err)
|
||||
time.Sleep(sleepDuration)
|
||||
|
||||
result, err = operation()
|
||||
if err == nil {
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
return result, fmt.Errorf("unable to complete operation after %d attempts, last error: %w", retryCount, err)
|
||||
}
|
||||
|
||||
func Lgetxattr(path string, attr string) ([]byte, error) {
|
||||
// Start with a 128 length byte array
|
||||
dest := make([]byte, 128)
|
||||
|
|
|
|||
|
|
@ -64,3 +64,41 @@ func TestRetry(t *testing.T) {
|
|||
t.Fatalf("Not expecting error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func makeRetryFuncWithResult(numFailures int) func() (int, error) {
|
||||
i := -1
|
||||
|
||||
return func() (int, error) {
|
||||
i++
|
||||
if i < numFailures {
|
||||
return i, fmt.Errorf("Failing with i=%v", i)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestRetryWithResult(t *testing.T) {
|
||||
// test with a function that does not return an error
|
||||
result, err := RetryWithResult(makeRetryFuncWithResult(0), 0, 10)
|
||||
if err != nil || result != 0 {
|
||||
t.Fatalf("Got result %d and error: %v", result, err)
|
||||
}
|
||||
result, err = RetryWithResult(makeRetryFuncWithResult(0), 3, 10)
|
||||
if err != nil || result != 0 {
|
||||
t.Fatalf("Got result %d and error: %v", result, err)
|
||||
}
|
||||
|
||||
// test with a function that returns an error twice
|
||||
result, err = RetryWithResult(makeRetryFuncWithResult(2), 0, 10)
|
||||
if err == nil || result != 0 {
|
||||
t.Fatalf("Got result %d and error: %v", result, err)
|
||||
}
|
||||
result, err = RetryWithResult(makeRetryFuncWithResult(2), 1, 10)
|
||||
if err == nil || result != 1 {
|
||||
t.Fatalf("Got result %d and error: %v", result, err)
|
||||
}
|
||||
result, err = RetryWithResult(makeRetryFuncWithResult(2), 2, 10)
|
||||
if err != nil || result != 2 {
|
||||
t.Fatalf("Got result %d and error: %v", result, err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue