From f633805b0626f1bf5c9becc267a9fec3194638ea Mon Sep 17 00:00:00 2001 From: Kingsley Chen Date: Sat, 28 Sep 2019 11:58:33 +0800 Subject: [PATCH 1/2] Fix bonus token by adjustavailableTokens() (#30) Once adjustavailableTokens() is called, the number of tokens should be updated in accordance with the tick even if the buket is full. Semantically, extra tokens are discarded though we, in fact, simply returns from the function. --- ratelimit.go | 2 +- ratelimit_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/ratelimit.go b/ratelimit.go index bd9ef10..b286ce5 100644 --- a/ratelimit.go +++ b/ratelimit.go @@ -310,6 +310,7 @@ func (tb *Bucket) currentTick(now time.Time) int64 { // available in the bucket at the given time, which must // be in the future (positive) with respect to tb.latestTick. func (tb *Bucket) adjustavailableTokens(tick int64) { + tb.latestTick = tick if tb.availableTokens >= tb.capacity { return } @@ -317,7 +318,6 @@ func (tb *Bucket) adjustavailableTokens(tick int64) { if tb.availableTokens > tb.capacity { tb.availableTokens = tb.capacity } - tb.latestTick = tick return } diff --git a/ratelimit_test.go b/ratelimit_test.go index 3de0cad..984efe4 100644 --- a/ratelimit_test.go +++ b/ratelimit_test.go @@ -382,6 +382,31 @@ func TestAvailable(t *testing.T) { } +func TestNoBonusTokenAfterBucketIsFull(t *testing.T) { + tb := NewBucketWithQuantum(time.Second*1, 100, 20) + curAvail := tb.Available() + if curAvail != 100 { + t.Fatalf("initially: actual available = %d, expected = %d", curAvail, 100) + } + + time.Sleep(time.Second * 5) + + curAvail = tb.Available() + if curAvail != 100 { + t.Fatalf("after pause: actual available = %d, expected = %d", curAvail, 100) + } + + cnt := tb.TakeAvailable(100) + if cnt != 100 { + t.Fatalf("taking: actual taken count = %d, expected = %d", cnt, 100) + } + + curAvail = tb.Available() + if curAvail != 0 { + t.Fatalf("after taken: actual available = %d, expected = %d", curAvail, 0) + } +} + func BenchmarkWait(b *testing.B) { tb := NewBucket(1, 16*1024) for i := b.N - 1; i >= 0; i-- { From 4b7d3ddde4ece170faae5643e6388c3aa94e1397 Mon Sep 17 00:00:00 2001 From: Kingsley Chen Date: Tue, 1 Oct 2019 21:55:36 +0800 Subject: [PATCH 2/2] Fix the stupid defect --- ratelimit.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ratelimit.go b/ratelimit.go index b286ce5..51a6559 100644 --- a/ratelimit.go +++ b/ratelimit.go @@ -310,11 +310,12 @@ func (tb *Bucket) currentTick(now time.Time) int64 { // available in the bucket at the given time, which must // be in the future (positive) with respect to tb.latestTick. func (tb *Bucket) adjustavailableTokens(tick int64) { + lastTick := tb.latestTick tb.latestTick = tick if tb.availableTokens >= tb.capacity { return } - tb.availableTokens += (tick - tb.latestTick) * tb.quantum + tb.availableTokens += (tick - lastTick) * tb.quantum if tb.availableTokens > tb.capacity { tb.availableTokens = tb.capacity }