2023-03-16 20:27:45 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type RateLimiter struct {
|
|
|
|
mu sync.Mutex
|
|
|
|
bucket map[string]int
|
|
|
|
rate int
|
2023-03-17 19:52:39 +01:00
|
|
|
burst int
|
2023-03-16 20:27:45 +01:00
|
|
|
}
|
|
|
|
|
2023-03-17 19:52:39 +01:00
|
|
|
func newRateLimiter(rate int, burst int) RateLimiter {
|
2023-03-16 20:27:45 +01:00
|
|
|
var rl = new(RateLimiter)
|
|
|
|
rl.bucket = make(map[string]int)
|
|
|
|
rl.rate = rate
|
2023-03-17 19:52:39 +01:00
|
|
|
rl.burst = burst
|
2023-03-16 20:27:45 +01:00
|
|
|
// Leak periodically
|
|
|
|
go func () {
|
|
|
|
for(true) {
|
|
|
|
rl.mu.Lock()
|
|
|
|
for addr, drips := range rl.bucket {
|
|
|
|
if drips <= rate {
|
|
|
|
delete(rl.bucket, addr)
|
|
|
|
} else {
|
|
|
|
rl.bucket[addr] = drips - rl.rate
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rl.mu.Unlock()
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return *rl
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rl *RateLimiter) Allowed(addr string) bool {
|
|
|
|
rl.mu.Lock()
|
|
|
|
defer rl.mu.Unlock()
|
|
|
|
drips, present := rl.bucket[addr]
|
|
|
|
if !present {
|
|
|
|
rl.bucket[addr] = 1
|
|
|
|
return true
|
|
|
|
}
|
2023-03-17 19:52:39 +01:00
|
|
|
if drips == rl.burst {
|
2023-03-16 20:27:45 +01:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
rl.bucket[addr] = drips + 1
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|