You've already forked agentic-coding-workflow
fix(app): give dispatcher.Shutdown its own ctx in ctx.Done branch
Final cross-cutting review finding: shutCtx was shared between server.Shutdown and dispatcher.Shutdown, with jobs.Stop's wall-clock time burning the budget in between. Under load, dispatcher.Shutdown could receive an already-dead ctx and skip draining in-flight async notify dispatches (including webhook enqueues). Mirror the errCh branch by creating a fresh 10s drainCtx for dispatcher.Shutdown.
This commit is contained in:
+7
-2
@@ -418,8 +418,13 @@ func (a *App) Run(ctx context.Context) error {
|
||||
a.jobs.Stop(stopCtx)
|
||||
stopCancel()
|
||||
}
|
||||
// server 已停止接收新请求;等异步通知投递结束再关 pool
|
||||
if err := a.dispatcher.Shutdown(shutCtx); err != nil {
|
||||
// server 已停止接收新请求;等异步通知投递结束再关 pool。
|
||||
// 用独立的 drainCtx:shutCtx 的 30s 预算已被 server.Shutdown 与
|
||||
// jobs.Stop 的实际墙钟时间消耗,复用可能让 dispatcher 拿到已死 ctx
|
||||
// 而立即返回,丢失在途的 webhook enqueue(DB 写)。
|
||||
drainCtx, drainCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer drainCancel()
|
||||
if err := a.dispatcher.Shutdown(drainCtx); err != nil {
|
||||
a.log.Warn("notify dispatcher drain", "err", err.Error())
|
||||
}
|
||||
a.pool.Close()
|
||||
|
||||
Reference in New Issue
Block a user