package ratelimit import ( "sync" "time" ) type Limiter struct { mu sync.Mutex rate float64 burst float64 buckets map[string]*bucket } type bucket struct { tokens float64 last time.Time } func New(rate, burst float64) *Limiter { return &Limiter{ rate: rate, burst: burst, buckets: make(map[string]*bucket), } } func (l *Limiter) Allow(key string) bool { now := time.Now() l.mu.Lock() defer l.mu.Unlock() b, ok := l.buckets[key] if !ok { l.buckets[key] = &bucket{tokens: l.burst - 1, last: now} return true } elapsed := now.Sub(b.last).Seconds() b.tokens += elapsed * l.rate if b.tokens > l.burst { b.tokens = l.burst } b.last = now if b.tokens < 1 { return false } b.tokens -= 1 return true }