修复旧麦位操作恢复阻断

This commit is contained in:
zhx 2026-07-07 20:09:43 +08:00
parent d9bfb014d8
commit dd8dc489b7
2 changed files with 36 additions and 2 deletions

View File

@ -327,7 +327,8 @@ func replay(current *state.RoomState, cmd command.Command, committedAtMS int64)
case *command.ChangeMicSeat:
from, exists := current.SeatByUser(typed.TargetUserID)
if !exists {
return fmt.Errorf("change_mic_seat replay target is not on seat: %d", typed.TargetUserID)
// 换麦位属于麦上用户操作;历史过期命令若晚于下麦/离房恢复到达,当前状态已无源麦位时保持 no-op。
return nil
}
fromIndex := current.SeatIndex(from.SeatNo)
toIndex := current.SeatIndex(typed.SeatNo)
@ -353,7 +354,8 @@ func replay(current *state.RoomState, cmd command.Command, committedAtMS int64)
case *command.SetMicMute:
seat, exists := current.SeatByUser(typed.TargetUserID)
if !exists {
return fmt.Errorf("set_mic_mute replay target is not on seat: %d", typed.TargetUserID)
// 静音状态只附着在当前麦位会话上;用户已不在麦上时,旧静音命令不能阻断房间恢复。
return nil
}
index := current.SeatIndex(seat.SeatNo)
current.MicSeats[index].MicMuted = typed.Muted

View File

@ -142,3 +142,35 @@ func TestReplayApplyRTCEventSkipsStaleMissingSeat(t *testing.T) {
t.Fatalf("stale rtc events must not mutate version, got %d", current.Version)
}
}
func TestReplayChangeMicSeatSkipsStaleMissingSeat(t *testing.T) {
current := state.NewRoomState("room-replay-stale-change-seat", 7601, 8, "voice")
current.OnlineUsers[7601] = &state.RoomUserState{UserID: 7601, Role: "owner", JoinedAtMS: 1000, LastSeenAtMS: 1000}
if err := replay(current, &command.ChangeMicSeat{
Base: command.Base{ActorID: 7601, Room: current.RoomID, SentAtMS: 2000},
TargetUserID: 7601,
SeatNo: 2,
}, 2000); err != nil {
t.Fatalf("stale change seat without source seat must be skipped: %v", err)
}
if current.Version != 0 {
t.Fatalf("stale change seat must not mutate version, got %d", current.Version)
}
}
func TestReplaySetMicMuteSkipsStaleMissingSeat(t *testing.T) {
current := state.NewRoomState("room-replay-stale-mute", 7701, 8, "voice")
current.OnlineUsers[7701] = &state.RoomUserState{UserID: 7701, Role: "owner", JoinedAtMS: 1000, LastSeenAtMS: 1000}
if err := replay(current, &command.SetMicMute{
Base: command.Base{ActorID: 7701, Room: current.RoomID, SentAtMS: 2000},
TargetUserID: 7701,
Muted: true,
}, 2000); err != nil {
t.Fatalf("stale mute without seat must be skipped: %v", err)
}
if current.Version != 0 {
t.Fatalf("stale mute must not mutate version, got %d", current.Version)
}
}