watchdog/internal/ratelimit/limiter.go
NotAShelf c3b77696aa
internal: centralize size/length constants; better DoS protection
...also adds a bounded custom event registry for cardinality control but
I ran out of space in the commit message. Praise be to the long
descriptions...

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ic205f69804c7fb24c39fa84abdd9546b6a6a6964
2026-03-02 22:38:00 +03:00

53 lines
1.1 KiB
Go

package ratelimit
import (
"sync"
"time"
)
// Implements a simple token bucket rate limiter
type TokenBucket struct {
mu sync.Mutex
tokens int
capacity int
refill int
interval time.Duration
lastFill time.Time
}
// Creates a rate limiter with specified capacity and refill rate capacity
func NewTokenBucket(capacity, refillPerInterval int, interval time.Duration) *TokenBucket {
return &TokenBucket{
tokens: capacity,
capacity: capacity,
refill: refillPerInterval,
interval: interval,
lastFill: time.Now(),
}
}
// Allow checks if a request should be allowed
func (tb *TokenBucket) Allow() bool {
tb.mu.Lock()
defer tb.mu.Unlock()
// Refill tokens based on elapsed time
now := time.Now()
elapsed := now.Sub(tb.lastFill)
if elapsed >= tb.interval {
periods := int(elapsed / tb.interval)
tb.tokens += periods * tb.refill
if tb.tokens > tb.capacity {
tb.tokens = tb.capacity
}
tb.lastFill = now.Add(-elapsed % tb.interval)
}
// Check if we have tokens available
if tb.tokens > 0 {
tb.tokens--
return true
}
return false
}