mirror of https://github.com/garrytan/gstack.git
Fix browse restart and resilient goto
This commit is contained in:
parent
eca0610e44
commit
7d48890e9b
|
|
@ -500,6 +500,15 @@ async function sendCommand(state: ServerState, command: string, args: string[],
|
|||
await writeStdout('Server stopped');
|
||||
return;
|
||||
}
|
||||
if (command === 'restart' && !(await isServerHealthy(state.port))) {
|
||||
const restartEnv: Record<string, string> = {};
|
||||
if (_globalFlags?.proxyUrl) restartEnv.BROWSE_PROXY_URL = _globalFlags.proxyUrl;
|
||||
if (_globalFlags?.headed) restartEnv.BROWSE_HEADED = '1';
|
||||
if (_globalFlags?.configHash) restartEnv.BROWSE_CONFIG_HASH = _globalFlags.configHash;
|
||||
await startServer(Object.keys(restartEnv).length ? restartEnv : undefined);
|
||||
await writeStdout('Server restarted');
|
||||
return;
|
||||
}
|
||||
if (retries >= 1) throw new Error('[browse] Server crashed twice in a row — aborting');
|
||||
console.error('[browse] Server connection lost. Restarting...');
|
||||
// Kill the old server to avoid orphaned chromium processes
|
||||
|
|
|
|||
|
|
@ -128,6 +128,24 @@ const CLEANUP_SELECTORS = {
|
|||
],
|
||||
};
|
||||
|
||||
async function withManualTimeout<T>(
|
||||
promise: Promise<T>,
|
||||
timeoutMs: number
|
||||
): Promise<{ timedOut: false; value: T } | { timedOut: true }> {
|
||||
promise.catch(() => {});
|
||||
let timeout: ReturnType<typeof setTimeout> | undefined;
|
||||
try {
|
||||
return await Promise.race([
|
||||
promise.then((value) => ({ timedOut: false as const, value })),
|
||||
new Promise<{ timedOut: true }>((resolve) => {
|
||||
timeout = setTimeout(() => resolve({ timedOut: true }), timeoutMs);
|
||||
}),
|
||||
]);
|
||||
} finally {
|
||||
if (timeout) clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleWriteCommand(
|
||||
command: string,
|
||||
args: string[],
|
||||
|
|
@ -148,9 +166,17 @@ export async function handleWriteCommand(
|
|||
// must not leave stale content that could resurrect on a later context recreation.
|
||||
session.clearLoadedHtml();
|
||||
const normalizedUrl = await validateNavigationUrl(url);
|
||||
const response = await page.goto(normalizedUrl, { waitUntil: 'domcontentloaded', timeout: 15000 });
|
||||
const response = await page.goto(normalizedUrl, { waitUntil: 'commit', timeout: 15000 });
|
||||
const domReady = await withManualTimeout(
|
||||
page.waitForLoadState('domcontentloaded', { timeout: 15000 }),
|
||||
16000
|
||||
);
|
||||
if (domReady.timedOut) {
|
||||
await page.evaluate(() => window.stop()).catch(() => {});
|
||||
}
|
||||
const status = response?.status() || 'unknown';
|
||||
return `Navigated to ${normalizedUrl} (${status})`;
|
||||
const suffix = domReady.timedOut ? '; domcontentloaded timed out' : '';
|
||||
return `Navigated to ${normalizedUrl} (${status}${suffix})`;
|
||||
}
|
||||
|
||||
case 'back': {
|
||||
|
|
|
|||
|
|
@ -332,6 +332,11 @@ describe('cli command dispatch', () => {
|
|||
expect(cliSource).not.toContain('IS_WINDOWS ? 2 : 1, result.stdout');
|
||||
});
|
||||
|
||||
test('restart connection loss starts once instead of resending restart', () => {
|
||||
expect(cliSource).toContain("if (command === 'restart' && !(await isServerHealthy(state.port)))");
|
||||
expect(cliSource).toContain("await writeStdout('Server restarted')");
|
||||
});
|
||||
|
||||
test('default headless cold-start does not print a delayed startup banner', () => {
|
||||
expect(cliSource).not.toContain("console.error('[browse] Starting server...')");
|
||||
expect(cliSource).toContain('Starting server in headed mode');
|
||||
|
|
@ -339,6 +344,16 @@ describe('cli command dispatch', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('write command dispatch', () => {
|
||||
const writeSource = fs.readFileSync(path.resolve(__dirname, '../src/write-commands.ts'), 'utf-8');
|
||||
|
||||
test('goto commits first and bounds domcontentloaded wait', () => {
|
||||
expect(writeSource).toContain("page.goto(normalizedUrl, { waitUntil: 'commit', timeout: 15000 })");
|
||||
expect(writeSource).toContain("page.waitForLoadState('domcontentloaded', { timeout: 15000 })");
|
||||
expect(writeSource).toContain("await page.evaluate(() => window.stop()).catch(() => {})");
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveGstackHome', () => {
|
||||
test('honors GSTACK_HOME env var when set', () => {
|
||||
const orig = process.env.GSTACK_HOME;
|
||||
|
|
|
|||
Loading…
Reference in New Issue