-
Notifications
You must be signed in to change notification settings - Fork 357
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: remove rate.Limiter and implement as requested.
- Loading branch information
Chris Stockton
committed
Sep 30, 2024
1 parent
00c0439
commit 994a9f4
Showing
3 changed files
with
90 additions
and
101 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 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 |
---|---|---|
@@ -1,27 +1,49 @@ | ||
package api | ||
|
||
import ( | ||
"sync" | ||
"time" | ||
|
||
"github.com/supabase/auth/internal/conf" | ||
"golang.org/x/time/rate" | ||
) | ||
|
||
// RateLimiter will limit the number of calls to Allow per interval. | ||
type RateLimiter struct { | ||
mu sync.Mutex | ||
ival time.Duration // Count is reset and time updated every ival. | ||
limit int // Limit calls to Allow() per ival. | ||
|
||
// Guarded by mu. | ||
last time.Time // When the limiter was last reset. | ||
count int // Total calls to Allow() since time. | ||
} | ||
|
||
// newRateLimiter returns a rate limiter configured using the given conf.Rate. | ||
// | ||
// The returned *rate.Limiter will be configured with a token bucket containing | ||
// a single token, which will fill up at a rate of r. For example to allow 100 | ||
// events every 24 hours. This will fill a token bucket approximately once every | ||
// 864 seconds (14.4 minutes). See Example_newRateLimiter for a visualization. | ||
func newRateLimiter(r conf.Rate) *rate.Limiter { | ||
// The rate limiter deals in events per second. | ||
eps := r.EventsPerSecond() | ||
burst := int(r.Events) | ||
if burst <= 0 { | ||
burst = 1 | ||
func newRateLimiter(r conf.Rate) *RateLimiter { | ||
return &RateLimiter{ | ||
ival: r.OverTime, | ||
limit: int(r.Events), | ||
last: time.Now(), | ||
} | ||
} | ||
|
||
// NewLimiter will have an initial token bucket of size `burst`. It will | ||
// be refilled at a rate of `eps` indefinitely. Note that the expression | ||
// 100 / 24h is roughly equivelant to the expression 1 / 15m. The 100 is | ||
// a rate, not a quota. | ||
return rate.NewLimiter(rate.Limit(eps), burst) | ||
func (rl *RateLimiter) Allow() bool { | ||
rl.mu.Lock() | ||
defer rl.mu.Unlock() | ||
|
||
now := time.Now() | ||
return rl.allowAt(now) | ||
} | ||
|
||
func (rl *RateLimiter) allowAt(at time.Time) bool { | ||
since := at.Sub(rl.last) | ||
if ivals := int64(since / rl.ival); ivals > 0 { | ||
rl.last = rl.last.Add(time.Duration(ivals) * rl.ival) | ||
rl.count = 0 | ||
} | ||
if rl.count < rl.limit { | ||
rl.count++ | ||
return true | ||
} | ||
return false | ||
} |
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