fix: cap persistent room queues at 200 entries

This commit is contained in:
DiheChen committed 2026-11-02 22:00:14 +08:00
1 parent f6be3c5044
commit b12dfcebb6
4 files changed
+33 -10

No files matched your search

+8 -7
View File
@@ -21,11 +21,12 @@ type Error struct {
func (e *Error) Error() string { return e.Message }
var (
ErrRateLimited = &Error{RateLimited, "操作过于频繁,请稍后再试。"}
errLinkForbidden = &Error{Forbidden, "临时房间只能点哔哩哔哩的链接。"}
errQueueFull = &Error{QueueFull, fmt.Sprintf("临时房间的播放列表最多 %d 首歌,等播放几首之后再点。", ephemeralQueueLimit)}
errDuplicatePick = &Error{Conflict, "这首歌已经在播放列表里了。"}
errNotInQueue = &Error{NotFound, "这首歌已经不在播放列表里了。"}
errNothingPlaying = &Error{NothingPlaying, "现在没有在放的歌。"}
errDuplicateVote = &Error{Conflict, "你已经投过票了。"}
ErrRateLimited = &Error{RateLimited, "操作过于频繁,请稍后再试。"}
errLinkForbidden = &Error{Forbidden, "临时房间只能点哔哩哔哩的链接。"}
errEphemeralQueueFull = &Error{QueueFull, fmt.Sprintf("临时房间的播放列表最多 %d 首歌,等播放几首之后再点。", ephemeralQueueLimit)}
errPersistentQueueFull = &Error{QueueFull, fmt.Sprintf("播放列表最多 %d 首歌,等播放几首之后再点。", persistentQueueLimit)}
errDuplicatePick = &Error{Conflict, "这首歌已经在播放列表里了。"}
errNotInQueue = &Error{NotFound, "这首歌已经不在播放列表里了。"}
errNothingPlaying = &Error{NothingPlaying, "现在没有在放的歌。"}
errDuplicateVote = &Error{Conflict, "你已经投过票了。"}
)
+9 -2
View File
@@ -40,6 +40,13 @@ func (r *Room) burst() int {
return EphemeralBurst
}
func (r *Room) queueLimit() (int, *Error) {
if r.info.Kind == Persistent {
return persistentQueueLimit, errPersistentQueueFull
}
return ephemeralQueueLimit, errEphemeralQueueFull
}
func (r *Room) enqueue(b *batch, by member.Member, a Enqueue) (Result, *Error) {
if !r.pickLimit.allow(b.now, r.burst(), RefillInterval) {
return nil, ErrRateLimited
@@ -47,8 +54,8 @@ func (r *Room) enqueue(b *batch, by member.Member, a Enqueue) (Result, *Error) {
if a.Track.Source == track.Link && r.info.Kind == Ephemeral {
return nil, errLinkForbidden
}
if r.info.Kind == Ephemeral && len(r.waiting) >= ephemeralQueueLimit {
return nil, errQueueFull
if limit, full := r.queueLimit(); len(r.waiting) >= limit {
return nil, full
}
if r.queued(a.Track) {
return nil, errDuplicatePick
+13
View File
@@ -34,6 +34,19 @@ func TestEphemeralRoomLimits(t *testing.T) {
wantError(t, r.Handle(at(13*time.Minute), enqueue(alice, netease("z"))), QueueFull)
}
func TestPersistentRoomQueueLimit(t *testing.T) {
r := newRoom(t, Persistent)
// 每分钟点一首,额度不会用完;第一首成为待播,之后 200 首进入等待队列。
for i := range 201 {
if res := reply(t, r.Handle(at(time.Duration(i+1)*time.Minute), enqueue(alice, netease(fmt.Sprint(i))))); res.Err != nil {
t.Fatalf("第 %d 首点歌失败:%#v", i+1, res)
}
}
if res := reply(t, r.Handle(at(203*time.Minute), enqueue(alice, netease("z")))); res.Err != errPersistentQueueFull {
t.Errorf("等待队列满 200 首后再点歌 = %#v,期望 errPersistentQueueFull", res.Err)
}
}
func TestRateLimitsByRoomKind(t *testing.T) {
cases := []struct {
name string
+3 -1
View File
@@ -16,7 +16,9 @@ const (
EphemeralBurst = 5
persistentBurst = 30
ephemeralQueueLimit = 10
chatLimit = 500
// 等待队列每次变化都要整体落盘,并向所有会话广播完整的队列,所以常驻房间也要有上限。
persistentQueueLimit = 200
chatLimit = 500
)
// Room 内部没有锁,同一个 Room 的 Handle 必须由调用方串行调用。