From 279b61198cf06970238da8e7eaed4979a0cb12c9 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Tue, 27 Oct 2026 15:58:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(scheduler):=20=E7=A9=BA=E9=97=B2=E6=97=B6?= =?UTF-8?q?=E5=85=A5=E9=98=9F=E4=B8=8D=E5=86=8D=E8=AF=AF=E6=8A=A5=20"level?= =?UTF-8?q?=20insufficient"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现场:日志满屏 [agent] interrupt queued: task#2 class=interrupt level=3 from qq (L3) vs (?) — level insufficient 而实际成因是"当前没有运行任务可抢占",与级别毫无关系。这类假因会 把运维引到"是不是级别配低了"的错误方向(本仓反复吃亏的静默/误导同族)。 改成四种成因分开写: idle (no running task; queued for next pick) / running in critical section / preempt cooldown / level insufficient --- internal/agent/core/scheduler.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/internal/agent/core/scheduler.go b/internal/agent/core/scheduler.go index 73008817..c60d26cd 100644 --- a/internal/agent/core/scheduler.go +++ b/internal/agent/core/scheduler.go @@ -328,10 +328,16 @@ func (s *scheduler) registerInterrupt(t *Task) bool { s.enqueueInterruptLocked(t) // 入队而不是抢占:这也是要能看见的(否则「中断明明到了却没生效」无从解释)。 // 两种成因分开写:临界区 vs 级别不够/冷却期。 + // 成因必须分开写,否则「中断明明到了却没生效」无从解释。 + // 特别地:**空闲时没有受害者可抢**,不该报 "level insufficient"—— + // 那会让运维以为级别配错了(实测日志里满屏 "vs (?) — level insufficient")。 reason := "level insufficient" - if critical { + switch { + case running == nil: + reason = "idle (no running task; queued for next pick)" + case critical: reason = "running in critical section" - } else if canPreempt(t, running) && running != nil && !running.LastPreemptAt.IsZero() && time.Since(running.LastPreemptAt) < preemptCooldown { + case canPreempt(t, running) && !running.LastPreemptAt.IsZero() && time.Since(running.LastPreemptAt) < preemptCooldown: reason = "preempt cooldown" } log.Printf("[agent] interrupt queued: %s from %s (L%d) vs %s (%s) — %s; queue=%d",