fix: time out agent-browser stale close (#3832)
This commit is contained in:
parent
d7c42b144a
commit
d23c754535
|
|
@ -157,6 +157,40 @@ describe('AgentBrowserBridge', () => {
|
|||
expect(clickCall![1]).not.toContain('--cdp')
|
||||
})
|
||||
|
||||
it('continues when stale agent-browser session close hangs during session creation', async () => {
|
||||
vi.useFakeTimers()
|
||||
try {
|
||||
const closeKill = vi.fn()
|
||||
execFileMock.mockImplementation(
|
||||
(_bin: string, args: string[], _opts: unknown, cb: Function) => {
|
||||
if (args.includes('close')) {
|
||||
return { kill: closeKill }
|
||||
}
|
||||
if (args.includes('snapshot')) {
|
||||
cb(null, JSON.stringify({ success: true, data: { snapshot: 'ready' } }), '')
|
||||
return { kill: vi.fn() }
|
||||
}
|
||||
throw new Error(`unexpected agent-browser args ${args.join(' ')}`)
|
||||
}
|
||||
)
|
||||
|
||||
const promise = bridge.snapshot()
|
||||
let settled = false
|
||||
void promise.finally(() => {
|
||||
settled = true
|
||||
})
|
||||
|
||||
await vi.advanceTimersByTimeAsync(3_000)
|
||||
await Promise.resolve()
|
||||
|
||||
expect(settled).toBe(true)
|
||||
await expect(promise).resolves.toEqual({ browserPageId: 'tab-1', snapshot: 'ready' })
|
||||
expect(closeKill).toHaveBeenCalled()
|
||||
} finally {
|
||||
vi.useRealTimers()
|
||||
}
|
||||
})
|
||||
|
||||
// ── --json always appended ──
|
||||
|
||||
it('always appends --json to commands', async () => {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import type {
|
|||
const EXEC_TIMEOUT_MS = 90_000
|
||||
const CONSECUTIVE_TIMEOUT_LIMIT = 3
|
||||
const WAIT_PROCESS_TIMEOUT_GRACE_MS = 1_000
|
||||
const STALE_SESSION_CLOSE_TIMEOUT_MS = 3_000
|
||||
|
||||
type SessionState = {
|
||||
proxy: CdpWsProxy
|
||||
|
|
@ -1917,11 +1918,7 @@ export class AgentBrowserBridge {
|
|||
// across Orca restarts. A stale session ignores --cdp (already initialized) and
|
||||
// connects to the dead port. Must await close so the daemon forgets the session
|
||||
// before we pass --cdp with the new port.
|
||||
await new Promise<void>((resolve) => {
|
||||
execFile(this.agentBrowserBin, ['--session', sessionName, 'close'], { timeout: 3000 }, () =>
|
||||
resolve()
|
||||
)
|
||||
})
|
||||
await this.closeStaleAgentBrowserSession(sessionName)
|
||||
|
||||
const proxy = new CdpWsProxy(wc)
|
||||
const cdpEndpoint = await proxy.start()
|
||||
|
|
@ -2097,6 +2094,40 @@ export class AgentBrowserBridge {
|
|||
return new BrowserError('browser_tab_not_found', pageUnavailableMessageForSession(sessionName))
|
||||
}
|
||||
|
||||
private closeStaleAgentBrowserSession(sessionName: string): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
let child: ReturnType<typeof execFile> | null = null
|
||||
let settled = false
|
||||
|
||||
const finish = (): void => {
|
||||
if (settled) {
|
||||
return
|
||||
}
|
||||
settled = true
|
||||
clearTimeout(timeout)
|
||||
resolve()
|
||||
}
|
||||
|
||||
// Why: this is best-effort daemon cleanup before creating a fresh session;
|
||||
// a wedged close command must not block the real browser action.
|
||||
const timeout = setTimeout(() => {
|
||||
child?.kill()
|
||||
finish()
|
||||
}, STALE_SESSION_CLOSE_TIMEOUT_MS)
|
||||
|
||||
try {
|
||||
child = execFile(
|
||||
this.agentBrowserBin,
|
||||
['--session', sessionName, 'close'],
|
||||
{ timeout: STALE_SESSION_CLOSE_TIMEOUT_MS },
|
||||
finish
|
||||
)
|
||||
} catch {
|
||||
finish()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private createCommandError(
|
||||
sessionName: string,
|
||||
message: string,
|
||||
|
|
|
|||
Loading…
Reference in New Issue