Skip to content
This repository has been archived by the owner on May 23, 2024. It is now read-only.

Fix bug of zero credit in rate limiter #614

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions utils/rate_limiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (

// RateLimiter is a filter used to check if a message that is worth itemCost units is within the rate limits.
//
// TODO (breaking change) remove this interface in favor of public struct below
// # TODO (breaking change) remove this interface in favor of public struct below
//
// Deprecated, use ReconfigurableRateLimiter.
type RateLimiter interface {
Expand Down Expand Up @@ -55,9 +55,13 @@ type ReconfigurableRateLimiter struct {

// NewRateLimiter creates a new ReconfigurableRateLimiter.
func NewRateLimiter(creditsPerSecond, maxBalance float64) *ReconfigurableRateLimiter {
balance := maxBalance
if creditsPerSecond == 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like it should be invalid condition to instantiate rate limiter with <=0 replenishment rate

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @yurishkuro.
I feel 0 maybe a valid condition which should have the same effect as {const, 0}.

Supporting zero case will be useful when we want to totally mute the signal from a service endpoint when remotely controlling the sampling from collector using the perOperation strategy. (Setting the probability to 0 is not enough and we have to set the lowerbound to 0 as well).

balance = 0
}
return &ReconfigurableRateLimiter{
creditsPerSecond: creditsPerSecond,
balance: maxBalance,
balance: balance,
maxBalance: maxBalance,
lastTick: time.Now(),
timeNow: time.Now,
Expand Down
16 changes: 16 additions & 0 deletions utils/rate_limiter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,22 @@ func TestRateLimiterMaxBalance(t *testing.T) {
assert.False(t, rl.CheckCredit(1.0))
}

func TestRateLimiterZeroCreditsPerSecond(t *testing.T) {
rl := NewRateLimiter(0, 1.0)
// stop time
ts := time.Now()
rl.lastTick = ts
rl.timeNow = func() time.Time {
return ts
}
assert.False(t, rl.CheckCredit(1.0), "on initialization, should not have any credit for 1 message")

rl.timeNow = func() time.Time {
return ts.Add(time.Second * 20)
}
assert.False(t, rl.CheckCredit(1.0))
}

func TestRateLimiterReconfigure(t *testing.T) {
rl := NewRateLimiter(1, 1.0)
assertBalance := func(expected float64) {
Expand Down