44 lines
890 B
Go
44 lines
890 B
Go
package retryutil
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type RetryError struct {
|
|
n int
|
|
}
|
|
|
|
func (e *RetryError) Error() string {
|
|
return fmt.Sprintf("still failing after %d retries", e.n)
|
|
}
|
|
|
|
type ConditionFunc func() (bool, error)
|
|
|
|
// Retry retries f every interval until after maxRetries.
|
|
// The interval won't be affected by how long f takes.
|
|
// For example, if interval is 3s, f takes 1s, another f will be called 2s later.
|
|
// However, if f takes longer than interval, it will be delayed.
|
|
func Retry(interval time.Duration, maxRetries int, f ConditionFunc) error {
|
|
if maxRetries <= 0 {
|
|
return fmt.Errorf("maxRetries (%d) should be > 0", maxRetries)
|
|
}
|
|
tick := time.NewTicker(interval)
|
|
defer tick.Stop()
|
|
|
|
for i := 0; ; i++ {
|
|
ok, err := f()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if ok {
|
|
return nil
|
|
}
|
|
if i+1 == maxRetries {
|
|
break
|
|
}
|
|
<-tick.C
|
|
}
|
|
return &RetryError{maxRetries}
|
|
}
|