2080062d8c
盲区:节点 status 只看 agent 的 gRPC 在线,sing-box 数据面坏了(崩/配置坏/数据口不通) 而 agent 仍在线时,节点仍显示 up、connect 放行、客户端「已连接」但流量全失败,且不自愈。 控制面: - agent 每心跳探 sing-box clash_api /version(2s 超时,连续 2 次失败才报不健康,防抖), 经新增 HeartbeatRequest.data_plane_healthy 上报(手写 agentv1 契约 + proto 同步;JSON codec)。 - NodeLoad 加 DataPlaneHealthy(随 load 写 Redis;字段缺失默认 healthy 防滚动期误杀)。 - effectiveNodeStatus 扩为 (dbStatus, agentOnline, dataPlaneHealthy);ListNodes 与 ConnectNode 统一改用它 → 数据面坏的节点列表置灰 + connect 返回 404 拦截。 客户端(connection_provider 连通看门狗): - 连上后每 15s 经隧道 HTTP 探海外 generate_204(可注入),连续 3 次失败判当前节点不可用。 - 智能选择 → 自动切到其他最优可用节点重连;手动选定 → 断开并提示「节点异常」(尊重用户选择)。 - 新增 nodeUnhealthySwitched/nodeUnhealthyError 文案。 测试:agent 健康探测防抖、effectiveNodeStatus 真值表、dataPlaneHealthy 助手、看门狗 智能切/手动断/健康不触发;go test ./... 与 flutter test 全绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
24 lines
749 B
Go
24 lines
749 B
Go
package agentd
|
|
|
|
import "testing"
|
|
|
|
// TestClashHealthSource_Debounce verifies the 2-strike debounce: a single failed
|
|
// probe is tolerated (sing-box restart window), two consecutive failures report
|
|
// unhealthy, and a success resets the strike counter.
|
|
func TestClashHealthSource_Debounce(t *testing.T) {
|
|
probeResults := []bool{true, false, false, false, true, false}
|
|
want := []bool{true, true, false, false, true, true}
|
|
// ↑ok ↑1st ↑2nd ↑3rd ↑ok ↑1st-after-reset
|
|
i := 0
|
|
h := &clashHealthSource{probe: func() bool {
|
|
r := probeResults[i]
|
|
i++
|
|
return r
|
|
}}
|
|
for n, w := range want {
|
|
if got := h.Healthy(); got != w {
|
|
t.Errorf("Healthy() call %d = %v, want %v (probe=%v)", n, got, w, probeResults[n])
|
|
}
|
|
}
|
|
}
|