-
Notifications
You must be signed in to change notification settings - Fork 0
Adding leaky bucket and adding support to both limiters in the registry #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,54 @@ | ||||||||||||||
| package bucket | ||||||||||||||
|
|
||||||||||||||
| import ( | ||||||||||||||
| "sync" | ||||||||||||||
| "time" | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| // LeakyLimiter implements a leaky bucket rate limiter. Requests fill the bucket, | ||||||||||||||
| // which drains at a constant rate. If the bucket is full, requests are rejected. | ||||||||||||||
| // Unlike TokenLimiter, this enforces a smooth output rate rather than allowing bursts. | ||||||||||||||
| type LeakyLimiter struct { | ||||||||||||||
| mu sync.Mutex | ||||||||||||||
|
|
||||||||||||||
| capacity, level, rate float64 | ||||||||||||||
| lastUpdatedAt time.Time | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
|
||||||||||||||
| // NewLeakyLimiter returns a new LeakyLimiter with the given capacity and leak rate. | |
| // capacity specifies the maximum number of tokens that can be accumulated in the | |
| // limiter, and rate specifies how many tokens per second leak from the bucket. | |
| // The returned *LeakyLimiter is initialized with an empty bucket and the current time. |
Copilot
AI
Jan 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exported method Allow lacks documentation. According to Go conventions, all exported methods should have doc comments describing their behavior.
| // Allow reports whether a new event is permitted under the current limiter | |
| // state and updates the internal level accordingly. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| package bucket_test | ||
|
|
||
| import ( | ||
| "sync" | ||
| "sync/atomic" | ||
| "testing" | ||
|
|
||
| "github.com/serroba/rate/bucket" | ||
| "github.com/stretchr/testify/assert" | ||
| ) | ||
|
|
||
| func TestLeakyLimiter_Allow(t *testing.T) { | ||
| type args struct { | ||
| capacity uint32 | ||
| rate uint32 | ||
| } | ||
|
|
||
| tests := []struct { | ||
| name string | ||
| args args | ||
| previousAttempts int | ||
| want bool | ||
| }{ | ||
| {name: "Test With No Capacity", args: args{capacity: 0, rate: 0}, want: false}, | ||
| {name: "Test With Capacity 1", args: args{capacity: 1, rate: 0}, want: true}, | ||
| { | ||
| name: "Test With Capacity 1 with previous attempt", | ||
| args: args{capacity: 1, rate: 0}, | ||
| previousAttempts: 1, | ||
| want: false, | ||
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| lim := bucket.NewLeakyLimiter(tt.args.capacity, tt.args.rate) | ||
| for range tt.previousAttempts { | ||
| lim.Allow() | ||
| } | ||
|
|
||
| assert.Equalf(t, tt.want, lim.Allow(), "Allow()") | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestLeakyLimiter_Allow_Concurrent(t *testing.T) { | ||
| var ( | ||
| allow atomic.Int64 | ||
| deny atomic.Int64 | ||
| wg sync.WaitGroup | ||
| ) | ||
|
|
||
| lim := bucket.NewLeakyLimiter(10, 5) | ||
|
|
||
| for range 15 { | ||
| wg.Add(1) | ||
|
|
||
| go func() { | ||
| defer wg.Done() | ||
|
|
||
| if lim.Allow() { | ||
| allow.Add(1) | ||
| } else { | ||
| deny.Add(1) | ||
| } | ||
| }() | ||
| } | ||
|
|
||
| wg.Wait() | ||
|
|
||
| assert.Equal(t, int64(10), allow.Load()) | ||
| assert.Equal(t, int64(5), deny.Load()) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exported type LeakyLimiter and its exported method Allow lack documentation comments. According to Go conventions, all exported types and methods should have doc comments that begin with the name being declared.