Tests for retry_utils

One can argue about how necessary they are,
but at least I remembered how to do golang.
This commit is contained in:
Dmitrii Dolgov
2018-02-07 17:04:43 +01:00
parent 60c742a3e8
commit dd79fcd036
2 changed files with 96 additions and 3 deletions
+28 -3
View File
@@ -5,14 +5,39 @@ import (
"time"
)
// Retry calls ConditionFunc until it returns boolean true, a timeout expires or an error occurs.
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, f, tick)
}
func RetryWorker(
interval time.Duration,
timeout time.Duration,
f func() (bool, error),
tick RetryTicker) error {
maxRetries := int(timeout / interval)
tick := time.NewTicker(interval)
defer tick.Stop()
for i := 0; ; i++ {
@@ -26,7 +51,7 @@ func Retry(interval time.Duration, timeout time.Duration, f func() (bool, error)
if i+1 == maxRetries {
break
}
<-tick.C
tick.Tick()
}
return fmt.Errorf("still failing after %d retries", maxRetries)
}