-
Notifications
You must be signed in to change notification settings - Fork 398
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add an optional burstable rate limiter
The existing rate limiter was moved to a separate package and renamed to IntervalLimiter. Added BurstLimiter which is a wrapper around the "golang.org/x/time/rate" package. The conf.Rate type now has a private `typ` field that indicates if it is a "interval" or "burst" rate limiter. If the config value is in the form of "<burst>/<rate>" we set it to "burst", otherwise "interval". The conf.Rate.GetRateType() method is then called from the ratelimit.New package to determine the underlying type of `ratelimit.Limiter` returned from `ratelimit.New`. Finally we changed `api.NewLimiterOptions` to call `ratelimit.New` instead of creating a specific type of rate limiter.
- Loading branch information
Chris Stockton
committed
Jan 22, 2025
1 parent
37e2349
commit 3746f70
Showing
11 changed files
with
521 additions
and
199 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package ratelimit | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/supabase/auth/internal/conf" | ||
"golang.org/x/time/rate" | ||
) | ||
|
||
const defaultOverTime = time.Hour | ||
|
||
// BurstLimiter wraps the golang.org/x/time/rate package. | ||
type BurstLimiter struct { | ||
rl *rate.Limiter | ||
} | ||
|
||
// NewBurstLimiter returns a rate limiter configured using the given conf.Rate. | ||
// | ||
// The returned Limiter will be configured with a token bucket containing a | ||
// single token, which will fill up at a rate of 1 event per r.OverTime with | ||
// an initial burst amount of r.Events. | ||
// | ||
// For example: | ||
// - 1/10s is 1 events per 10 seconds with burst of 1. | ||
// - 1/2s is 1 events per 2 seconds with burst of 1. | ||
// - 10/10s is 1 events per 10 seconds with burst of 10. | ||
// | ||
// If Rate.Events is <= 0, the burst amount will be set to 1. | ||
// | ||
// See Example_newBurstLimiter for a visualization. | ||
func NewBurstLimiter(r conf.Rate) *BurstLimiter { | ||
// The rate limiter deals in events per second. | ||
d := r.OverTime | ||
if d <= 0 { | ||
d = defaultOverTime | ||
} | ||
|
||
e := r.Events | ||
if e <= 0 { | ||
e = 1 | ||
} | ||
|
||
// BurstLimiter will have an initial token bucket of size `e`. It will | ||
// be refilled at a rate of 1 per duration `d` indefinitely. | ||
rl := &BurstLimiter{ | ||
rl: rate.NewLimiter(rate.Every(d), int(e)), | ||
} | ||
return rl | ||
} | ||
|
||
// Allow implements Limiter by calling AllowAt with the current time. | ||
func (l *BurstLimiter) Allow() bool { | ||
return l.AllowAt(time.Now()) | ||
} | ||
|
||
// AllowAt implements Limiter by calling the underlying x/time/rate.Limiter | ||
// with the given time. | ||
func (l *BurstLimiter) AllowAt(at time.Time) bool { | ||
return l.rl.AllowN(at, 1) | ||
} |
Oops, something went wrong.