Files
jiang13-bbs/backend/service/ratelimit.go
freefire b9ba8cb8c9 feat: 类型帖互动、积分经济与发帖体验
补齐问答采纳/重开、投票匿名与有票禁编、悬赏过期退回、抽奖回帖开奖,并接入积分账本与发帖附件可见性。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 03:17:07 +08:00

86 lines
1.9 KiB
Go

package service
import (
"sync"
"time"
)
// RateLimiter 内存速率限制器
type RateLimiter struct {
mu sync.Mutex
records map[string][]time.Time
limits map[string]int // key -> 每分钟最大请求数
cooldown map[string]time.Duration
}
func NewRateLimiter() *RateLimiter {
return &RateLimiter{
records: make(map[string][]time.Time),
limits: make(map[string]int),
cooldown: make(map[string]time.Duration),
}
}
// SetLimit 设置某类请求的每分钟限制
func (r *RateLimiter) SetLimit(key string, perMinute int) {
r.mu.Lock()
defer r.mu.Unlock()
r.limits[key] = perMinute
}
// Allow 检查是否允许请求
func (r *RateLimiter) Allow(key string) bool {
r.mu.Lock()
defer r.mu.Unlock()
limit, ok := r.limits[key]
if !ok {
return true
}
now := time.Now()
windowStart := now.Add(-1 * time.Minute)
// 清理过期记录
records := r.records[key]
valid := records[:0]
for _, t := range records {
if t.After(windowStart) {
valid = append(valid, t)
}
}
if len(valid) >= limit {
r.records[key] = valid
return false
}
valid = append(valid, now)
r.records[key] = valid
return true
}
// 速率限制类型常量
const (
RateLogin = "login"
RateRegister = "register"
RatePost = "post"
RateComment = "comment"
RateChat = "chat" // 群聊发消息
RateUpload = "upload" // 帖子插图等上传
RateInteract = "interact" // 投票/抽奖/解锁等互动
)
// DefaultRateLimiter 创建默认速率限制器
func DefaultRateLimiter() *RateLimiter {
rl := NewRateLimiter()
rl.SetLimit(RateLogin, 20) // 登录 20/分钟
rl.SetLimit(RateRegister, 10) // 注册 10/分钟
rl.SetLimit(RatePost, 10) // 发帖 10/分钟
rl.SetLimit(RateComment, 30) // 评论 30/分钟
rl.SetLimit(RateChat, 30) // 群聊消息 30/分钟
rl.SetLimit(RateUpload, 20) // 图片上传 20/分钟
rl.SetLimit(RateInteract, 40) // 互动 40/分钟
return rl
}