postgres-operator/pkg/util/retryutil/retry_util.go

58 lines
1.1 KiB
Go

package retryutil
import (
"fmt"
"time"
)
type RetryTicker interface {
Stop()
Tick()
}
type Ticker struct {
ticker *time.Ticker
}
func (t *Ticker) Stop() { t.ticker.Stop() }
func (t *Ticker) Tick() { <-t.ticker.C }
// Retry calls ConditionFunc until either:
// * it returns boolean true
// * a timeout expires
// * an error occurs
func Retry(interval time.Duration, timeout time.Duration, f func() (bool, error)) error {
//TODO: make the retry exponential
if timeout < interval {
return fmt.Errorf("timout(%s) should be greater than interval(%v)", timeout, interval)
}
tick := &Ticker{time.NewTicker(interval)}
return RetryWorker(interval, timeout, tick, f)
}
func RetryWorker(
interval time.Duration,
timeout time.Duration,
tick RetryTicker,
f func() (bool, error)) error {
maxRetries := int(timeout / 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.Tick()
}
return fmt.Errorf("still failing after %d retries", maxRetries)
}