git init
This commit is contained in:
53
control-plane/backend/limiter.go
Normal file
53
control-plane/backend/limiter.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type loginEntry struct {
|
||||
window time.Time
|
||||
count int
|
||||
seen time.Time
|
||||
}
|
||||
|
||||
type LoginLimiter struct {
|
||||
mu sync.Mutex
|
||||
entries map[string]loginEntry
|
||||
limit int
|
||||
window time.Duration
|
||||
maxKeys int
|
||||
}
|
||||
|
||||
func NewLoginLimiter(limit int, window time.Duration) *LoginLimiter {
|
||||
return &LoginLimiter{entries: make(map[string]loginEntry), limit: limit, window: window, maxKeys: 10000}
|
||||
}
|
||||
|
||||
func (limiter *LoginLimiter) Allow(key string, now time.Time) bool {
|
||||
limiter.mu.Lock()
|
||||
defer limiter.mu.Unlock()
|
||||
_, known := limiter.entries[key]
|
||||
if !known && len(limiter.entries) >= limiter.maxKeys {
|
||||
cutoff := now.Add(-2 * limiter.window)
|
||||
for item, entry := range limiter.entries {
|
||||
if entry.seen.Before(cutoff) {
|
||||
delete(limiter.entries, item)
|
||||
}
|
||||
}
|
||||
if len(limiter.entries) >= limiter.maxKeys {
|
||||
return false
|
||||
}
|
||||
}
|
||||
entry := limiter.entries[key]
|
||||
if entry.window.IsZero() || now.Sub(entry.window) >= limiter.window {
|
||||
entry.window, entry.count = now, 0
|
||||
}
|
||||
entry.seen = now
|
||||
if entry.count >= limiter.limit {
|
||||
limiter.entries[key] = entry
|
||||
return false
|
||||
}
|
||||
entry.count++
|
||||
limiter.entries[key] = entry
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user