thread-master/backend/internal/library/ratelimit/token_bucket.go

63 lines
1.0 KiB
Go
Raw Permalink Normal View History

2026-06-27 16:03:28 +00:00
package ratelimit
import (
"sync"
"time"
)
type TokenBucket struct {
mu sync.Mutex
capacity int
tokens int
refillRate float64 // tokens per second
lastRefill time.Time
}
func NewTokenBucket(capacity int, refillPerSecond float64) *TokenBucket {
return &TokenBucket{
capacity: capacity,
tokens: capacity,
refillRate: refillPerSecond,
lastRefill: time.Now(),
}
}
func (tb *TokenBucket) Allow() bool {
return tb.AllowN(1)
}
func (tb *TokenBucket) AllowN(n int) bool {
tb.mu.Lock()
defer tb.mu.Unlock()
tb.refill()
if tb.tokens >= n {
tb.tokens -= n
return true
}
return false
}
func (tb *TokenBucket) Remaining() int {
tb.mu.Lock()
defer tb.mu.Unlock()
tb.refill()
return tb.tokens
}
func (tb *TokenBucket) Capacity() int {
return tb.capacity
}
func (tb *TokenBucket) refill() {
now := time.Now()
elapsed := now.Sub(tb.lastRefill).Seconds()
tb.lastRefill = now
add := int(elapsed * tb.refillRate)
if add > 0 {
tb.tokens += add
if tb.tokens > tb.capacity {
tb.tokens = tb.capacity
}
}
}