fix(gateway): avoid probe false negatives after connect

This commit is contained in:
Vincent Koc
2026-03-23 08:49:31 -07:00
parent 1e5f38a1a8
commit 93df5f613e
2 changed files with 29 additions and 3 deletions

View File

@@ -64,12 +64,23 @@ export async function probeGateway(opts: {
return await new Promise<GatewayProbeResult>((resolve) => {
let settled = false;
let timer: ReturnType<typeof setTimeout> | null = null;
const clearProbeTimer = () => {
if (timer) {
clearTimeout(timer);
timer = null;
}
};
const armProbeTimer = (onTimeout: () => void) => {
clearProbeTimer();
timer = setTimeout(onTimeout, clampProbeTimeoutMs(opts.timeoutMs));
};
const settle = (result: Omit<GatewayProbeResult, "url">) => {
if (settled) {
return;
}
settled = true;
clearTimeout(timer);
clearProbeTimer();
client.stop();
resolve({ url: opts.url, ...result });
};
@@ -105,6 +116,20 @@ export async function probeGateway(opts: {
});
return;
}
// Once the gateway has accepted the session, a slow follow-up RPC should no longer
// downgrade the probe to "unreachable". Give detail fetching its own budget.
armProbeTimer(() => {
settle({
ok: false,
connectLatencyMs,
error: "timeout",
close,
health: null,
status: null,
presence: null,
configSnapshot: null,
});
});
try {
if (detailLevel === "presence") {
const presence = await client.request("system-presence");
@@ -151,7 +176,7 @@ export async function probeGateway(opts: {
},
});
const timer = setTimeout(() => {
armProbeTimer(() => {
settle({
ok: false,
connectLatencyMs,
@@ -162,7 +187,7 @@ export async function probeGateway(opts: {
presence: null,
configSnapshot: null,
});
}, clampProbeTimeoutMs(opts.timeoutMs));
});
client.start();
});