2026-05-02 13:02:38 +08:00

93 lines
2.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"context"
"time"
"hyapp/pkg/appcode"
"hyapp/pkg/idgen"
"hyapp/services/room-service/internal/room/command"
"hyapp/services/room-service/internal/room/state"
)
const micDownReasonPublishTimeout = "publish_timeout"
// RunMicPublishTimeoutWorker 周期性释放超过 deadline 仍未确认 RTC 发流的麦位。
func (s *Service) RunMicPublishTimeoutWorker(ctx context.Context, interval time.Duration) {
if interval <= 0 || s.micPublishTimeout <= 0 {
// 非正数表示显式关闭,便于测试或临时止血。
return
}
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
_ = s.SweepMicPublishTimeouts(ctx)
}
}
}
// SweepMicPublishTimeouts 扫描本节点已装载 Room Cell自动下掉未确认发流的 pending_publish 麦位。
func (s *Service) SweepMicPublishTimeouts(ctx context.Context) error {
now := s.clock.Now()
nowMs := now.UnixMilli()
for _, roomRef := range s.loadedRoomRefs() {
roomCtx := appcode.WithContext(ctx, roomRef.AppCode)
roomCell := s.loadCell(roomCtx, roomRef.RoomID)
if roomCell == nil {
continue
}
currentState, _, err := roomCell.Snapshot(roomCtx)
if err != nil {
return err
}
for _, seat := range pendingPublishTimedOutSeats(currentState, nowMs) {
cmd := command.MicDown{
Base: command.Base{
RequestID: idgen.New("req_mic_publish_timeout"),
CommandID: idgen.New("cmd_mic_publish_timeout"),
ActorID: seat.UserID,
Room: roomRef.RoomID,
GatewayNodeID: s.nodeID,
SessionID: "mic-publish-timeout",
SentAtMS: nowMs,
},
TargetUserID: seat.UserID,
MicSessionID: seat.MicSessionID,
Reason: micDownReasonPublishTimeout,
}
if _, err := s.micDown(roomCtx, cmd); err != nil {
return err
}
}
}
return nil
}
func pendingPublishTimedOutSeats(current *state.RoomState, nowMs int64) []state.MicSeat {
if current == nil {
return nil
}
seats := make([]state.MicSeat, 0)
for _, seat := range current.MicSeats {
if seat.UserID <= 0 || seat.MicSessionID == "" {
continue
}
if seat.PublishState == state.MicPublishPending && seat.PublishDeadlineMS > 0 && seat.PublishDeadlineMS <= nowMs {
// 返回值拷贝,后续 MicDown 还会用 mic_session_id 在当前 Cell 状态中二次校验。
seats = append(seats, seat)
}
}
return seats
}