93 lines
2.4 KiB
Go
93 lines
2.4 KiB
Go
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
|
||
}
|