package services import ( "sync" "time" ) type RateLimiter struct { mu sync.Mutex attempts map[string][]time.Time max int window time.Duration } func NewRateLimiter(max int, window time.Duration) *RateLimiter { return &RateLimiter{ attempts: make(map[string][]time.Time), max: max, window: window, } } func (rl *RateLimiter) Allow(key string) bool { rl.mu.Lock() defer rl.mu.Unlock() now := time.Now() cutoff := now.Add(-rl.window) // Remove expired entries valid := rl.attempts[key][:0] for _, t := range rl.attempts[key] { if t.After(cutoff) { valid = append(valid, t) } } if len(valid) >= rl.max { rl.attempts[key] = valid return false } rl.attempts[key] = append(valid, now) return true }