File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ // Package ratelimit implements a token-bucket limiter to protect API
2+ // endpoints from abuse.
3+ package ratelimit
4+
5+ import (
6+ "sync"
7+ "time"
8+ )
9+
10+ // Limiter is a token-bucket rate limiter safe for concurrent use.
11+ type Limiter struct {
12+ mu sync.Mutex
13+ tokens float64
14+ capacity float64
15+ refillRate float64
16+ last time.Time
17+ }
18+
19+ // NewLimiter returns a Limiter that allows up to capacity requests in a
20+ // burst, refilling at refillRate tokens per second.
21+ func NewLimiter (capacity , refillRate float64 ) * Limiter {
22+ return & Limiter {
23+ tokens : capacity ,
24+ capacity : capacity ,
25+ refillRate : refillRate ,
26+ last : time .Now (),
27+ }
28+ }
29+
30+ // Allow reports whether a single request may proceed now, consuming one
31+ // token if so.
32+ func (l * Limiter ) Allow () bool {
33+ l .mu .Lock ()
34+ defer l .mu .Unlock ()
35+
36+ now := time .Now ()
37+ elapsed := now .Sub (l .last ).Seconds ()
38+ l .last = now
39+
40+ l .tokens += elapsed * l .refillRate
41+ if l .tokens > l .capacity {
42+ l .tokens = l .capacity
43+ }
44+ if l .tokens < 1 {
45+ return false
46+ }
47+ l .tokens --
48+ return true
49+ }
You can’t perform that action at this time.
0 commit comments