grain/config/rateLimiter.go

132 lines
3.1 KiB
Go
Raw Normal View History

2024-07-30 15:27:38 +00:00
package config
2024-07-25 03:04:26 +00:00
import (
2024-07-26 14:02:34 +00:00
"fmt"
2024-07-31 15:56:55 +00:00
config "grain/config/types"
2024-07-25 03:04:26 +00:00
"sync"
"golang.org/x/time/rate"
)
type KindLimiter struct {
Limiter *rate.Limiter
Limit rate.Limit
Burst int
}
type CategoryLimiter struct {
Limiter *rate.Limiter
Limit rate.Limit
Burst int
}
2024-07-25 03:04:26 +00:00
type RateLimiter struct {
2024-07-25 13:57:24 +00:00
wsLimiter *rate.Limiter
2024-07-26 01:33:42 +00:00
eventLimiter *rate.Limiter
2024-07-26 14:02:34 +00:00
reqLimiter *rate.Limiter
categoryLimiters map[string]*CategoryLimiter
2024-07-26 01:33:42 +00:00
kindLimiters map[int]*KindLimiter
2024-07-25 13:57:24 +00:00
mu sync.RWMutex
2024-07-25 03:04:26 +00:00
}
2024-07-25 13:57:24 +00:00
var rateLimiterInstance *RateLimiter
2024-08-03 18:27:58 +00:00
var rateOnce sync.Once
2024-07-25 13:57:24 +00:00
2024-07-31 15:56:55 +00:00
func SetupRateLimiter(cfg *config.ServerConfig) {
2024-07-30 15:51:05 +00:00
rateLimiter := NewRateLimiter(
rate.Limit(cfg.RateLimit.WsLimit),
cfg.RateLimit.WsBurst,
rate.Limit(cfg.RateLimit.EventLimit),
cfg.RateLimit.EventBurst,
rate.Limit(cfg.RateLimit.ReqLimit),
cfg.RateLimit.ReqBurst,
)
for _, kindLimit := range cfg.RateLimit.KindLimits {
rateLimiter.AddKindLimit(kindLimit.Kind, rate.Limit(kindLimit.Limit), kindLimit.Burst)
}
for category, categoryLimit := range cfg.RateLimit.CategoryLimits {
rateLimiter.AddCategoryLimit(category, rate.Limit(categoryLimit.Limit), categoryLimit.Burst)
}
SetRateLimiter(rateLimiter)
}
2024-07-25 20:43:46 +00:00
func SetRateLimiter(rl *RateLimiter) {
2024-08-03 18:27:58 +00:00
rateOnce.Do(func() {
2024-07-25 20:43:46 +00:00
rateLimiterInstance = rl
})
}
func GetRateLimiter() *RateLimiter {
return rateLimiterInstance
}
2024-07-26 14:02:34 +00:00
func NewRateLimiter(wsLimit rate.Limit, wsBurst int, eventLimit rate.Limit, eventBurst int, reqLimit rate.Limit, reqBurst int) *RateLimiter {
2024-07-25 03:04:26 +00:00
return &RateLimiter{
2024-07-25 13:57:24 +00:00
wsLimiter: rate.NewLimiter(wsLimit, wsBurst),
2024-07-26 01:33:42 +00:00
eventLimiter: rate.NewLimiter(eventLimit, eventBurst),
2024-07-26 14:02:34 +00:00
reqLimiter: rate.NewLimiter(reqLimit, reqBurst),
categoryLimiters: make(map[string]*CategoryLimiter),
2024-07-26 01:33:42 +00:00
kindLimiters: make(map[int]*KindLimiter),
2024-07-25 03:04:26 +00:00
}
}
2024-07-26 14:02:34 +00:00
func (rl *RateLimiter) AllowWs() (bool, string) {
if !rl.wsLimiter.Allow() {
return false, "WebSocket message rate limit exceeded"
}
return true, ""
}
2024-07-26 14:02:34 +00:00
func (rl *RateLimiter) AllowEvent(kind int, category string) (bool, string) {
2024-07-25 03:04:26 +00:00
rl.mu.RLock()
defer rl.mu.RUnlock()
if !rl.eventLimiter.Allow() {
2024-07-26 14:02:34 +00:00
return false, "Global event rate limit exceeded"
2024-07-25 03:04:26 +00:00
}
if kindLimiter, exists := rl.kindLimiters[kind]; exists {
if !kindLimiter.Limiter.Allow() {
2024-07-26 14:02:34 +00:00
return false, fmt.Sprintf("Rate limit exceeded for kind: %d", kind)
2024-07-25 03:04:26 +00:00
}
}
if categoryLimiter, exists := rl.categoryLimiters[category]; exists {
if !categoryLimiter.Limiter.Allow() {
2024-07-26 14:02:34 +00:00
return false, fmt.Sprintf("Rate limit exceeded for category: %s", category)
}
}
2024-07-26 14:02:34 +00:00
return true, ""
}
func (rl *RateLimiter) AllowReq() (bool, string) {
if !rl.reqLimiter.Allow() {
return false, "REQ rate limit exceeded"
}
return true, ""
2024-07-25 03:04:26 +00:00
}
2024-07-25 20:43:46 +00:00
func (rl *RateLimiter) AddCategoryLimit(category string, limit rate.Limit, burst int) {
rl.mu.Lock()
defer rl.mu.Unlock()
rl.categoryLimiters[category] = &CategoryLimiter{
Limiter: rate.NewLimiter(limit, burst),
Limit: limit,
Burst: burst,
}
2024-07-25 13:57:24 +00:00
}
2024-07-25 20:43:46 +00:00
func (rl *RateLimiter) AddKindLimit(kind int, limit rate.Limit, burst int) {
rl.mu.Lock()
defer rl.mu.Unlock()
rl.kindLimiters[kind] = &KindLimiter{
Limiter: rate.NewLimiter(limit, burst),
Limit: limit,
Burst: burst,
}
2024-07-25 13:57:24 +00:00
}