package server import ( "context" "time" ) // startChatTurnSweeper 周期清理孤儿 chat 回合(T20-B5): // status=processing 且租约过期的回合批量标 failed,防止崩溃/超时后 // 幂等键被永久占位。间隔保守(2 分钟),批上限 200。 func (s *Server) startChatTurnSweeper() { if s == nil || s.ctxMgr() == nil { return } stopCh, ok := s.chatTurnSweepLoop.start() if !ok { return } go func() { t := time.NewTicker(2 * time.Minute) defer t.Stop() for { select { case <-stopCh: return case <-t.C: // 独立超时,避免扫描被慢查询拖住 drain 窗口。 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) _, _ = s.ctxMgr().SweepExpiredProcessingTurns(ctx, 200) cancel() } } }() }