Files
openclaw/src/gateway/channel-health-policy.test.ts
ql-wade a5c07fa115 fix(gateway): skip stale-socket restarts for Telegram polling (openclaw#38405)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: ql-wade <262266039+ql-wade@users.noreply.github.com>
2026-03-07 00:20:34 -06:00

159 lines
4.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { evaluateChannelHealth, resolveChannelRestartReason } from "./channel-health-policy.js";
describe("evaluateChannelHealth", () => {
it("treats disabled accounts as healthy unmanaged", () => {
const evaluation = evaluateChannelHealth(
{
running: false,
enabled: false,
configured: true,
},
{
channelId: "discord",
now: 100_000,
channelConnectGraceMs: 10_000,
staleEventThresholdMs: 30_000,
},
);
expect(evaluation).toEqual({ healthy: true, reason: "unmanaged" });
});
it("uses channel connect grace before flagging disconnected", () => {
const evaluation = evaluateChannelHealth(
{
running: true,
connected: false,
enabled: true,
configured: true,
lastStartAt: 95_000,
},
{
channelId: "discord",
now: 100_000,
channelConnectGraceMs: 10_000,
staleEventThresholdMs: 30_000,
},
);
expect(evaluation).toEqual({ healthy: true, reason: "startup-connect-grace" });
});
it("treats active runs as busy even when disconnected", () => {
const now = 100_000;
const evaluation = evaluateChannelHealth(
{
running: true,
connected: false,
enabled: true,
configured: true,
activeRuns: 1,
lastRunActivityAt: now - 30_000,
},
{
channelId: "discord",
now,
channelConnectGraceMs: 10_000,
staleEventThresholdMs: 30_000,
},
);
expect(evaluation).toEqual({ healthy: true, reason: "busy" });
});
it("flags stale busy channels as stuck when run activity is too old", () => {
const now = 100_000;
const evaluation = evaluateChannelHealth(
{
running: true,
connected: false,
enabled: true,
configured: true,
activeRuns: 1,
lastRunActivityAt: now - 26 * 60_000,
},
{
channelId: "discord",
now,
channelConnectGraceMs: 10_000,
staleEventThresholdMs: 30_000,
},
);
expect(evaluation).toEqual({ healthy: false, reason: "stuck" });
});
it("ignores inherited busy flags until current lifecycle reports run activity", () => {
const now = 100_000;
const evaluation = evaluateChannelHealth(
{
running: true,
connected: false,
enabled: true,
configured: true,
lastStartAt: now - 30_000,
busy: true,
activeRuns: 1,
lastRunActivityAt: now - 31_000,
},
{
channelId: "discord",
now,
channelConnectGraceMs: 10_000,
staleEventThresholdMs: 30_000,
},
);
expect(evaluation).toEqual({ healthy: false, reason: "disconnected" });
});
it("flags stale sockets when no events arrive beyond threshold", () => {
const evaluation = evaluateChannelHealth(
{
running: true,
connected: true,
enabled: true,
configured: true,
lastStartAt: 0,
lastEventAt: null,
},
{
channelId: "discord",
now: 100_000,
channelConnectGraceMs: 10_000,
staleEventThresholdMs: 30_000,
},
);
expect(evaluation).toEqual({ healthy: false, reason: "stale-socket" });
});
it("skips stale-socket detection for telegram long-polling channels", () => {
const evaluation = evaluateChannelHealth(
{
running: true,
connected: true,
enabled: true,
configured: true,
lastStartAt: 0,
lastEventAt: null,
},
{
channelId: "telegram",
now: 100_000,
channelConnectGraceMs: 10_000,
staleEventThresholdMs: 30_000,
},
);
expect(evaluation).toEqual({ healthy: true, reason: "healthy" });
});
});
describe("resolveChannelRestartReason", () => {
it("maps not-running + high reconnect attempts to gave-up", () => {
const reason = resolveChannelRestartReason(
{
running: false,
reconnectAttempts: 10,
},
{ healthy: false, reason: "not-running" },
);
expect(reason).toBe("gave-up");
});
});