Fixed integer overflow bug in rate limiter.

pull/6/head
Anirudh 2016-08-24 16:47:08 -07:00
parent 1952986a34
commit 00e41888b0
2 changed files with 41 additions and 1 deletions

View File

@ -90,9 +90,16 @@ func (r *ItemExponentialFailureRateLimiter) When(item interface{}) time.Duration
r.failuresLock.Lock()
defer r.failuresLock.Unlock()
exp := r.failures[item]
r.failures[item] = r.failures[item] + 1
calculated := r.baseDelay * time.Duration(math.Pow10(r.failures[item]-1))
// The backoff is capped such that 'calculated' value never overflows.
backoff := float64(r.baseDelay.Nanoseconds()) * math.Pow10(exp)
if backoff > math.MaxInt64 {
return r.maxDelay
}
calculated := time.Duration(backoff)
if calculated > r.maxDelay {
return r.maxDelay
}

View File

@ -63,6 +63,39 @@ func TestItemExponentialFailureRateLimiter(t *testing.T) {
}
func TestItemExponentialFailureRateLimiterOverFlow(t *testing.T) {
limiter := NewItemExponentialFailureRateLimiter(1*time.Millisecond, 1000*time.Second)
for i := 0; i < 5; i++ {
limiter.When("one")
}
if e, a := 100000*time.Millisecond, limiter.When("one"); e != a {
t.Errorf("expected %v, got %v", e, a)
}
for i := 0; i < 1000; i++ {
limiter.When("overflow1")
}
if e, a := 1000*time.Second, limiter.When("overflow1"); e != a {
t.Errorf("expected %v, got %v", e, a)
}
limiter = NewItemExponentialFailureRateLimiter(1*time.Minute, 1000*time.Hour)
for i := 0; i < 2; i++ {
limiter.When("two")
}
if e, a := 100*time.Minute, limiter.When("two"); e != a {
t.Errorf("expected %v, got %v", e, a)
}
for i := 0; i < 1000; i++ {
limiter.When("overflow2")
}
if e, a := 1000*time.Hour, limiter.When("overflow2"); e != a {
t.Errorf("expected %v, got %v", e, a)
}
}
func TestItemFastSlowRateLimiter(t *testing.T) {
limiter := NewItemFastSlowRateLimiter(5*time.Millisecond, 10*time.Second, 3)