rate: the state of the limiter should not be changed when the requests failed
In the following cases, the reserveN is a no-op, and the state of
the limiter should not be changed:
1. n exceeds the Limiter's burst size
2. maxFutureReserve is less than the waitDuration
Fixes golang/go#52584
Change-Id: I5f38afa5da696bc10178a4bd0640d92062a8b009
GitHub-Last-Rev: e408718f070679209aca64bfbc18e4297777c311
GitHub-Pull-Request: golang/time#22
Reviewed-on: https://go-review.googlesource.com/c/time/+/406154
Reviewed-by: Russ Cox <rsc@golang.org>
Auto-Submit: Sameer Ajmani <sameer@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Sameer Ajmani <sameer@golang.org>
Auto-Submit: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
diff --git a/rate/rate.go b/rate/rate.go
index 8f7c29f..f0e0cf3 100644
--- a/rate/rate.go
+++ b/rate/rate.go
@@ -83,7 +83,7 @@
// TokensAt returns the number of tokens available at time t.
func (lim *Limiter) TokensAt(t time.Time) float64 {
lim.mu.Lock()
- _, _, tokens := lim.advance(t) // does not mutute lim
+ _, tokens := lim.advance(t) // does not mutate lim
lim.mu.Unlock()
return tokens
}
@@ -183,7 +183,7 @@
return
}
// advance time to now
- t, _, tokens := r.lim.advance(t)
+ t, tokens := r.lim.advance(t)
// calculate new number of tokens
tokens += restoreTokens
if burst := float64(r.lim.burst); tokens > burst {
@@ -304,7 +304,7 @@
lim.mu.Lock()
defer lim.mu.Unlock()
- t, _, tokens := lim.advance(t)
+ t, tokens := lim.advance(t)
lim.last = t
lim.tokens = tokens
@@ -321,7 +321,7 @@
lim.mu.Lock()
defer lim.mu.Unlock()
- t, _, tokens := lim.advance(t)
+ t, tokens := lim.advance(t)
lim.last = t
lim.tokens = tokens
@@ -356,7 +356,7 @@
}
}
- t, last, tokens := lim.advance(t)
+ t, tokens := lim.advance(t)
// Calculate the remaining number of tokens resulting from the request.
tokens -= float64(n)
@@ -379,15 +379,11 @@
if ok {
r.tokens = n
r.timeToAct = t.Add(waitDuration)
- }
- // Update state
- if ok {
+ // Update state
lim.last = t
lim.tokens = tokens
lim.lastEvent = r.timeToAct
- } else {
- lim.last = last
}
return r
@@ -396,7 +392,7 @@
// advance calculates and returns an updated state for lim resulting from the passage of time.
// lim is not changed.
// advance requires that lim.mu is held.
-func (lim *Limiter) advance(t time.Time) (newT time.Time, newLast time.Time, newTokens float64) {
+func (lim *Limiter) advance(t time.Time) (newT time.Time, newTokens float64) {
last := lim.last
if t.Before(last) {
last = t
@@ -409,7 +405,7 @@
if burst := float64(lim.burst); tokens > burst {
tokens = burst
}
- return t, last, tokens
+ return t, tokens
}
// durationFromTokens is a unit conversion function from the number of tokens to the duration
diff --git a/rate/rate_test.go b/rate/rate_test.go
index d0d9149..a063e35 100644
--- a/rate/rate_test.go
+++ b/rate/rate_test.go
@@ -427,6 +427,12 @@
runReserve(t, lim, request{t1, 2, t1, true}) // start at t1
runReserve(t, lim, request{t0, 1, t1, true}) // should violate Limit,Burst
runReserve(t, lim, request{t2, 2, t3, true})
+ // burst size is 2, so n=3 always fails, and the state of lim should not be changed
+ runReserve(t, lim, request{t0, 3, time.Time{}, false})
+ runReserve(t, lim, request{t2, 1, t4, true})
+ // the maxReserve is not enough so it fails, and the state of lim should not be changed
+ runReserveMax(t, lim, request{t0, 2, time.Time{}, false}, d)
+ runReserve(t, lim, request{t2, 1, t5, true})
}
func TestReserveJumpBackCancel(t *testing.T) {