TokenBucket limiter with burst capacity and refill
Go
package ratelimit
import (
"sync"
"time"
)
// Bucket is a token bucket: it allows bursts up to capacity while refilling at
// ratePerSec tokens per second.
type Bucket struct {
mu sync.Mutex
capacity float64
rate float64
tokens float64
last time.Time
}
// NewBucket starts with a full bucket, so the first capacity calls succeed.
func NewBucket(capacity, ratePerSec float64) *Bucket {
return &Bucket{capacity: capacity, rate: ratePerSec, tokens: capacity, last: time.Now()}
}
// Allow consumes n tokens if enough have accrued, otherwise it returns false.
func (b *Bucket) Allow(n float64) bool {
b.mu.Lock()
defer b.mu.Unlock()
now := time.Now()
b.tokens = min(b.capacity, b.tokens+now.Sub(b.last).Seconds()*b.rate)
b.last = now
if b.tokens < n {
return false
}
b.tokens -= n
return true
}