From 29150065aa9e4034e1d9c37aa73c8b11f37d742f Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Sun, 25 Oct 2026 22:31:51 +0800 Subject: [PATCH] =?UTF-8?q?fix(clawhub):=20sidecar=20=E5=B0=B1=E7=BB=AA?= =?UTF-8?q?=E8=B6=85=E6=97=B6=205s=20=E2=86=92=2030s=EF=BC=88=E6=85=A2?= =?UTF-8?q?=E6=9C=BA=E5=99=A8=E4=B8=8A=20node=20=E5=86=B7=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E8=B6=85=E6=97=B6=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI 报红:`TestLaunchSidecarAndListTools` launch sidecar: sidecar echoplugin ping timeout (5.00s) 本机全绿。 ## 这不是"测试机器慢所以放宽测试" sidecar 起不来等于该 skill 整体不可用 —— 这是**产品行为**,不是测试细节。 原来的 5s 是按开发机估算的:node 冷启动 + 模块加载在快盘空载时约 0.2s。 而 CI 共享 runner(以及真实部署里的低配机器)上,一次 fork+exec+node 引导遇到 CPU 争抢就会超过 5s。 判断"真的挂了"应该由**进程退出信号**负责(readLoop 会感知), 而不是由引导耗时猜。 ## 30s 的取法 · 比 systemd 的 TimeoutStopSec(25s) 宽 —— 关停时不该被就绪等待拖住 · 与用户可感知的"卡住"阈值(约 30s)持平 —— 再长就该让用户看到明确失败 · 错误文案带上超时值与可能原因(node 不可用),便于自助排查 --- internal/plugins/clawhubadapter/sidecar.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/internal/plugins/clawhubadapter/sidecar.go b/internal/plugins/clawhubadapter/sidecar.go index ba0b9349..5d8493ae 100644 --- a/internal/plugins/clawhubadapter/sidecar.go +++ b/internal/plugins/clawhubadapter/sidecar.go @@ -228,6 +228,23 @@ func launchProcessIn(bin, arg, dir, name, simDir, workDir string) (*sidecarProce return sp, nil } +// sidecarReadyTimeout 是等 sidecar 回第一个 ping 的上限。 +// +// ★ 从固定 5s 放宽到 30s(2026-10-25 修 CI 误报)。 +// +// 原来的 5s 是**按开发机估算**的:node 冷启动 + 模块加载在快盘上空载时 +// 约 0.2s。而 CI 的共享 runner(以及真实部署里的低配机器)上,一次 +// fork+exec+node 引导遇到 CPU 争抢就会到 5s 以上,实测 CI 报 +// `sidecar echoplugin ping timeout` 而本机全绿。 +// +// 这不是"测试环境太慢所以放宽测试"——它是**产品行为**:sidecar 起不来 +// 等于该 skill 整体不可用。给足时间是正确取舍;判断"真的挂了"应由进程 +// 退出信号负责(readLoop 会感知),而不是由引导耗时猜。 +// +// 30s 的取法:比 systemd 的 TimeoutStopSec(25s) 宽,比用户可感知的 +// "卡住"阈值(约 30s)持平——再长就该让用户看到明确失败。 +const sidecarReadyTimeout = 30 * time.Second + func (s *sidecarProcess) waitReady() error { done := make(chan error, 1) go func() { @@ -237,8 +254,9 @@ func (s *sidecarProcess) waitReady() error { select { case err := <-done: return err - case <-time.After(5 * time.Second): - return fmt.Errorf("sidecar %s ping timeout", s.name) + case <-time.After(sidecarReadyTimeout): + return fmt.Errorf("sidecar %s ping timeout(%v 内未响应;慢机器上 node 冷启动可能更久,"+ + "若持续失败请检查 node 是否可用)", s.name, sidecarReadyTimeout) } }