2021-05-01 12:45:37 +02:00
|
|
|
package util
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/rand"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2021-05-15 12:24:30 +02:00
|
|
|
// Retry retries a given toExec function calling onError on failed attempts
|
2021-05-01 12:45:37 +02:00
|
|
|
// onError shouldn be a lightweight function and shouldn't be blocking
|
|
|
|
func Retry(attempts int, sleep time.Duration, toExec func() error, onError func(e error)) error {
|
|
|
|
if err := toExec(); err != nil {
|
|
|
|
if s, ok := err.(stop); ok {
|
|
|
|
return s.error
|
|
|
|
}
|
|
|
|
|
|
|
|
if attempts--; attempts > 0 {
|
|
|
|
jitter := time.Duration(rand.Int63n(int64(sleep)))
|
|
|
|
sleep = sleep + jitter/2
|
|
|
|
|
|
|
|
onError(err)
|
|
|
|
time.Sleep(sleep)
|
|
|
|
return Retry(attempts, 2*sleep, toExec, onError)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type stop struct {
|
|
|
|
error
|
|
|
|
}
|