fix: cap persistent room queues at 200 entries
This commit is contained in:
1 parent
f6be3c5044
commit
b12dfcebb6
4 files changed
+33
-10
No files matched your search
@@ -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, "你已经投过票了。"}
|
||||
)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -16,7 +16,9 @@ const (
|
||||
EphemeralBurst = 5
|
||||
persistentBurst = 30
|
||||
ephemeralQueueLimit = 10
|
||||
chatLimit = 500
|
||||
// 等待队列每次变化都要整体落盘,并向所有会话广播完整的队列,所以常驻房间也要有上限。
|
||||
persistentQueueLimit = 200
|
||||
chatLimit = 500
|
||||
)
|
||||
|
||||
// Room 内部没有锁,同一个 Room 的 Handle 必须由调用方串行调用。
|
||||
|
||||
Reference in new issue
Block a user