Browse Source

rate: ignore burst in WaitN when rate limit is Inf

WaitN fails when the number of tokens requested exceeds the limiter's
burst size, even when the rate limit is Inf.  The documented behavior is
that the burst size is ignored when the rate limit is Inf.  Change WaitN
to conform with the documentation, and add tests.

Fixes golang/go#16854

Change-Id: I3ca0a8dac47641c76bed4258cd7010f0a704ff8c
Reviewed-on: https://go-review.googlesource.com/28610
Run-TryBot: Sameer Ajmani <sameer@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Sameer Ajmani 9 years ago
parent
commit
711ca1cb87
2 changed files with 9 additions and 2 deletions
  1. 2 1
      rate/rate.go
  2. 7 1
      rate/rate_test.go

+ 2 - 1
rate/rate.go

@@ -221,8 +221,9 @@ func (lim *Limiter) Wait(ctx context.Context) (err error) {
 // WaitN blocks until lim permits n events to happen.
 // WaitN blocks until lim permits n events to happen.
 // It returns an error if n exceeds the Limiter's burst size, the Context is
 // It returns an error if n exceeds the Limiter's burst size, the Context is
 // canceled, or the expected wait time exceeds the Context's Deadline.
 // canceled, or the expected wait time exceeds the Context's Deadline.
+// The burst limit is ignored if the rate limit is Inf.
 func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) {
 func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) {
-	if n > lim.burst {
+	if n > lim.burst && lim.limit != Inf {
 		return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst)
 		return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst)
 	}
 	}
 	// Check if ctx is already cancelled
 	// Check if ctx is already cancelled

+ 7 - 1
rate/rate_test.go

@@ -396,7 +396,7 @@ func TestWaitSimple(t *testing.T) {
 	cancel()
 	cancel()
 	runWait(t, lim, wait{"already-cancelled", ctx, 1, 0, false})
 	runWait(t, lim, wait{"already-cancelled", ctx, 1, 0, false})
 
 
-	runWait(t, lim, wait{"n-gt-burst", context.Background(), 4, 0, false})
+	runWait(t, lim, wait{"exceed-burst-error", context.Background(), 4, 0, false})
 
 
 	runWait(t, lim, wait{"act-now", context.Background(), 2, 0, true})
 	runWait(t, lim, wait{"act-now", context.Background(), 2, 0, true})
 	runWait(t, lim, wait{"act-later", context.Background(), 3, 2, true})
 	runWait(t, lim, wait{"act-later", context.Background(), 3, 2, true})
@@ -426,6 +426,12 @@ func TestWaitTimeout(t *testing.T) {
 	runWait(t, lim, wait{"w-timeout-err", ctx, 3, 0, false})
 	runWait(t, lim, wait{"w-timeout-err", ctx, 3, 0, false})
 }
 }
 
 
+func TestWaitInf(t *testing.T) {
+	lim := NewLimiter(Inf, 0)
+
+	runWait(t, lim, wait{"exceed-burst-no-error", context.Background(), 3, 0, true})
+}
+
 func BenchmarkAllowN(b *testing.B) {
 func BenchmarkAllowN(b *testing.B) {
 	lim := NewLimiter(Every(1*time.Second), 1)
 	lim := NewLimiter(Every(1*time.Second), 1)
 	now := time.Now()
 	now := time.Now()