chore: refresh gramsrv public release

This commit is contained in:
A 2026-06-30 14:37:43 +08:00
parent 75cebe8dbf
commit 70b6820474
1274 changed files with 378751 additions and 59919 deletions

View file

@ -0,0 +1,90 @@
package rpc
import (
"context"
"time"
"go.uber.org/zap"
"telesrv/internal/domain"
"telesrv/internal/sfu"
)
// GroupCallSweepDispatcher 清理群通话幽灵参与者kill 进程/断电后无人发 leave
//
// ⚠ P0-2 活性契约:客户端只在 Connecting 态发 checkGroupCall媒体连通后心跳停止
// 单凭 last_check_date 判死会把所有连上媒体的健康参与者踢光。约定的判据是
// 「max(心跳, 媒体面活性)」M0SFU disabled客户端恒 Connecting、4s 心跳不断,
// 纯水位成立M1 起 SFU 必须对媒体面存活ICE consent/近期 SRTP 收包)的 endpoint
// 周期性刷新 last_check_dateliveness reporter使单一水位同时承载两路活性。
type GroupCallSweepDispatcher struct {
router *Router
log *zap.Logger
interval time.Duration
checkTTL time.Duration
batch int
}
func NewGroupCallSweepDispatcher(router *Router, log *zap.Logger, interval, checkTTL time.Duration) *GroupCallSweepDispatcher {
if log == nil {
log = zap.NewNop()
}
if interval <= 0 {
interval = 10 * time.Second
}
if checkTTL <= 0 {
checkTTL = 45 * time.Second
}
return &GroupCallSweepDispatcher{router: router, log: log, interval: interval, checkTTL: checkTTL, batch: 100}
}
func (d *GroupCallSweepDispatcher) Run(ctx context.Context) {
if d == nil || d.router == nil {
return
}
ticker := time.NewTicker(d.interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
d.DispatchOnce(ctx)
}
}
}
func (d *GroupCallSweepDispatcher) DispatchOnce(ctx context.Context) {
if d == nil || d.router == nil || d.router.deps.GroupCalls == nil {
return
}
now := d.router.clock.Now()
cutoff := int(now.Add(-d.checkTTL).Unix())
muts, err := d.router.deps.GroupCalls.SweepStale(ctx, cutoff, int(now.Unix()), d.batch)
if err != nil {
d.log.Warn("sweep group call participants", zap.Error(err))
return
}
for _, mut := range muts {
if d.router.deps.SFU != nil {
_ = d.router.deps.SFU.Leave(ctx, mut.Call.ID, mut.Participant.UserID, sfu.EndpointMain)
}
channel, err := d.router.channelForGroupCall(ctx, mut.Call)
if err != nil {
continue
}
d.router.groupCallMutationFanout(ctx, channel, mut)
d.log.Info("group call participant swept",
zap.Int64("call_id", mut.Call.ID),
zap.Int64("user_id", mut.Participant.UserID))
}
}
// channelForGroupCall 取通话所属频道行(推送 hydration 用)。
func (r *Router) channelForGroupCall(ctx context.Context, call domain.GroupCall) (domain.Channel, error) {
view, err := r.deps.Channels.GetChannel(ctx, call.CreatorUserID, call.ChannelID)
if err != nil {
return domain.Channel{}, err
}
return view.Channel, nil
}