mirror of
https://github.com/garrytan/gstack.git
synced 2026-08-22 14:07:14 +02:00
test: watchdog E2E in 1.5s instead of 22.7s (tunable poll interval)
server.ts gains BROWSE_WATCHDOG_INTERVAL_MS (floor 50ms, default 15s unchanged). The #994 stay-alive test runs a 250ms tick and waits for the stay-alive log line instead of blind-sleeping 2s + 20s past the production interval. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
43e77d84af
commit
da30a3cb5a
@@ -696,6 +696,13 @@ const BROWSE_PARENT_PID = parseInt(process.env.BROWSE_PARENT_PID || '0', 10);
|
|||||||
// the closure every 15s. The CLI's connect path sets BROWSE_HEADED=1 + PID=0,
|
// the closure every 15s. The CLI's connect path sets BROWSE_HEADED=1 + PID=0,
|
||||||
// so this branch is the normal path for /open-gstack-browser.
|
// so this branch is the normal path for /open-gstack-browser.
|
||||||
const IS_HEADED_WATCHDOG = process.env.BROWSE_HEADED === '1';
|
const IS_HEADED_WATCHDOG = process.env.BROWSE_HEADED === '1';
|
||||||
|
// Poll interval is env-tunable so the watchdog E2E test can use a ~250ms tick
|
||||||
|
// instead of waiting out the production 15s interval (was a 20s blind sleep).
|
||||||
|
// Floor of 50ms guards against a typo'd 0 busy-looping the server.
|
||||||
|
const WATCHDOG_INTERVAL_MS = (() => {
|
||||||
|
const raw = parseInt(process.env.BROWSE_WATCHDOG_INTERVAL_MS || '', 10);
|
||||||
|
return Number.isFinite(raw) && raw >= 50 ? raw : 15_000;
|
||||||
|
})();
|
||||||
if (BROWSE_PARENT_PID > 0 && !IS_HEADED_WATCHDOG) {
|
if (BROWSE_PARENT_PID > 0 && !IS_HEADED_WATCHDOG) {
|
||||||
let parentGone = false;
|
let parentGone = false;
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
@@ -723,7 +730,7 @@ if (BROWSE_PARENT_PID > 0 && !IS_HEADED_WATCHDOG) {
|
|||||||
console.log(`[browse] Parent process ${BROWSE_PARENT_PID} exited (server stays alive, idle timeout will clean up)`);
|
console.log(`[browse] Parent process ${BROWSE_PARENT_PID} exited (server stays alive, idle timeout will clean up)`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 15_000);
|
}, WATCHDOG_INTERVAL_MS);
|
||||||
} else if (IS_HEADED_WATCHDOG) {
|
} else if (IS_HEADED_WATCHDOG) {
|
||||||
console.log('[browse] Parent-process watchdog disabled (headed mode)');
|
console.log('[browse] Parent-process watchdog disabled (headed mode)');
|
||||||
} else if (BROWSE_PARENT_PID === 0) {
|
} else if (BROWSE_PARENT_PID === 0) {
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ import * as os from 'os';
|
|||||||
// /pair-agent users (server lingers after disconnect).
|
// /pair-agent users (server lingers after disconnect).
|
||||||
//
|
//
|
||||||
// Each test spawns the real server.ts. Tests 1 and 2 verify behavior via
|
// Each test spawns the real server.ts. Tests 1 and 2 verify behavior via
|
||||||
// stdout log line (fast). Test 3 waits for the watchdog poll cycle to confirm
|
// stdout log line (fast). Test 3 shrinks the watchdog tick to 250ms via
|
||||||
// the server REMAINS alive after parent death (slow — ~20s observation window).
|
// BROWSE_WATCHDOG_INTERVAL_MS and waits for the stay-alive log line, then
|
||||||
|
// confirms the server survived parent death (~1-2s instead of a 20s sleep).
|
||||||
|
|
||||||
const ROOT = path.resolve(import.meta.dir, '..');
|
const ROOT = path.resolve(import.meta.dir, '..');
|
||||||
const SERVER_SCRIPT = path.join(ROOT, 'src', 'server.ts');
|
const SERVER_SCRIPT = path.join(ROOT, 'src', 'server.ts');
|
||||||
@@ -137,21 +138,26 @@ describe('parent-process watchdog (v0.18.1.0)', () => {
|
|||||||
const parentPid = parentProc.pid!;
|
const parentPid = parentProc.pid!;
|
||||||
|
|
||||||
// Default headless: no BROWSE_HEADED, real parent PID — watchdog active.
|
// Default headless: no BROWSE_HEADED, real parent PID — watchdog active.
|
||||||
serverProc = spawnServer({ BROWSE_PARENT_PID: String(parentPid) }, 34903);
|
// 250ms tick (test-only knob) so this test doesn't wait out the
|
||||||
|
// production 15s interval; the old version blind-slept 22s.
|
||||||
|
serverProc = spawnServer(
|
||||||
|
{ BROWSE_PARENT_PID: String(parentPid), BROWSE_WATCHDOG_INTERVAL_MS: '250' },
|
||||||
|
34903,
|
||||||
|
);
|
||||||
const serverPid = serverProc.pid!;
|
const serverPid = serverProc.pid!;
|
||||||
|
|
||||||
// Give the server a moment to start and register the watchdog interval.
|
// Give the server a beat to register the watchdog interval.
|
||||||
await Bun.sleep(2000);
|
await Bun.sleep(500);
|
||||||
expect(isProcessAlive(serverPid)).toBe(true);
|
expect(isProcessAlive(serverPid)).toBe(true);
|
||||||
|
|
||||||
// Kill the parent. The watchdog polls every 15s, so first tick after
|
// Kill the parent. Pre-#994 the server would shut down on the next tick.
|
||||||
// parent death lands within ~15s. Pre-#994 the server would shutdown
|
// Post-#994 it logs the parent exit and stays alive — wait for that log
|
||||||
// here. Post-#994 the server logs the parent exit and stays alive.
|
// line instead of sleeping past a fixed interval.
|
||||||
parentProc.kill('SIGKILL');
|
parentProc.kill('SIGKILL');
|
||||||
|
const out = await readStdoutUntil(serverProc, 'server stays alive', 10_000);
|
||||||
// Wait long enough for at least one watchdog tick (15s) plus margin.
|
expect(out).toContain(
|
||||||
// Server should still be alive — that's the whole point of #994.
|
`Parent process ${parentPid} exited (server stays alive, idle timeout will clean up)`,
|
||||||
await Bun.sleep(20_000);
|
);
|
||||||
expect(isProcessAlive(serverPid)).toBe(true);
|
expect(isProcessAlive(serverPid)).toBe(true);
|
||||||
}, 45_000);
|
}, 30_000);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user