- Server no longer mirrors app.Runtime services (gov/svc/pwSvc/...): 574 call sites now use accessors in runtime_accessors.go - backgroundLoop (mutex+sync.Once) stops sweeper/publisher/reminder/wsGC goroutines race-free (baseline44161d2areproduced DATA RACE; now green under -race) - goose 00071 duplicate (dialogue merge1da17a28brought two 00071): context-conflict-adjudications renumbered to 00072; dev DB applied only through 00070 so zero data migration - task_finalize tests build minimal app.Runtime; test injection via serverTestOverrides + setOverride* (explicit-nil markers for fail-closed cases)
35 lines
803 B
Go
35 lines
803 B
Go
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()
|
|
}
|
|
}
|
|
}()
|
|
}
|