Add ForAttempt

See documentation for motivation.
This commit is contained in:
Keegan Carruthers-Smith 2016-03-01 17:31:41 +02:00
parent 2ff7c46940
commit 741535fc02
2 changed files with 26 additions and 3 deletions

View File

@ -22,6 +22,16 @@ type Backoff struct {
//Returns the current value of the counter and then //Returns the current value of the counter and then
//multiplies it Factor //multiplies it Factor
func (b *Backoff) Duration() time.Duration { func (b *Backoff) Duration() time.Duration {
d := b.ForAttempt(b.attempts)
b.attempts++
return d
}
// ForAttempt returns the duration for a specific attempt. This is useful if
// you have a large number of independent Backoffs, but don't want use
// unnecessary memory storing the Backoff parameters per Backoff. The first
// attempt should be 0.
func (b *Backoff) ForAttempt(attempt float64) time.Duration {
//Zero-values are nonsensical, so we use //Zero-values are nonsensical, so we use
//them to apply defaults //them to apply defaults
if b.Min == 0 { if b.Min == 0 {
@ -34,7 +44,7 @@ func (b *Backoff) Duration() time.Duration {
b.Factor = 2 b.Factor = 2
} }
//calculate this duration //calculate this duration
dur := float64(b.Min) * math.Pow(b.Factor, b.attempts) dur := float64(b.Min) * math.Pow(b.Factor, attempt)
if b.Jitter == true { if b.Jitter == true {
dur = rand.Float64()*(dur-float64(b.Min)) + float64(b.Min) dur = rand.Float64()*(dur-float64(b.Min)) + float64(b.Min)
} }
@ -42,8 +52,6 @@ func (b *Backoff) Duration() time.Duration {
if dur > float64(b.Max) { if dur > float64(b.Max) {
return b.Max return b.Max
} }
//bump attempts count
b.attempts++
//return as a time.Duration //return as a time.Duration
return time.Duration(dur) return time.Duration(dur)
} }

View File

@ -20,6 +20,21 @@ func Test1(t *testing.T) {
equals(t, b.Duration(), 100*time.Millisecond) equals(t, b.Duration(), 100*time.Millisecond)
} }
func TestForAttempt(t *testing.T) {
b := &Backoff{
Min: 100 * time.Millisecond,
Max: 10 * time.Second,
Factor: 2,
}
equals(t, b.ForAttempt(0), 100*time.Millisecond)
equals(t, b.ForAttempt(1), 200*time.Millisecond)
equals(t, b.ForAttempt(2), 400*time.Millisecond)
b.Reset()
equals(t, b.ForAttempt(0), 100*time.Millisecond)
}
func Test2(t *testing.T) { func Test2(t *testing.T) {
b := &Backoff{ b := &Backoff{