mirror of
https://github.com/stablyai/orca.git
synced 2026-10-17 16:02:55 +00:00
fix(terminal): retry every dead split renderer
This commit is contained in:
@@ -301,6 +301,47 @@ describe('requestTerminalPaneRecovery', () => {
|
||||
secondSplit.unregister()
|
||||
})
|
||||
|
||||
it('does not abandon a certified sibling behind a failed liveness retry', async () => {
|
||||
vi.useFakeTimers()
|
||||
vi.setSystemTime(0)
|
||||
await requestTerminalPaneRecovery({
|
||||
tabId: 'tab-1',
|
||||
ptyId: 'pty-initial',
|
||||
reason: 'write-stalled'
|
||||
})
|
||||
const recoveryGeneration = captureTerminalPaneRecoveryGeneration('tab-1')
|
||||
const livenessSplit = registerTerminalPaneRecoveryInstance('tab-1')
|
||||
const certifiedSplit = registerTerminalPaneRecoveryInstance('tab-1')
|
||||
mocks.hasPty.mockResolvedValue(false)
|
||||
|
||||
await requestTerminalPaneRecovery({
|
||||
tabId: 'tab-1',
|
||||
ptyId: 'pty-not-live',
|
||||
reason: 'input-undeliverable',
|
||||
terminalRecoveryGeneration: recoveryGeneration,
|
||||
terminalRecoveryInstanceId: livenessSplit.id,
|
||||
requireAuthoritativeLiveness: true
|
||||
})
|
||||
await requestTerminalPaneRecovery({
|
||||
tabId: 'tab-1',
|
||||
ptyId: 'pty-certified-dead',
|
||||
reason: 'write-stalled',
|
||||
terminalRecoveryGeneration: recoveryGeneration,
|
||||
terminalRecoveryInstanceId: certifiedSplit.id
|
||||
})
|
||||
|
||||
await vi.advanceTimersByTimeAsync(15_000)
|
||||
|
||||
expect(mocks.hasPty).toHaveBeenCalledWith('pty-not-live')
|
||||
expect(mocks.remountTerminalTabForRecovery).toHaveBeenCalledTimes(2)
|
||||
expect(mocks.recordRendererCrashBreadcrumb).toHaveBeenLastCalledWith(
|
||||
'terminal_pane_recovery_remount',
|
||||
{ tabId: 'tab-1', reason: 'write-stalled' }
|
||||
)
|
||||
livenessSplit.unregister()
|
||||
certifiedSplit.unregister()
|
||||
})
|
||||
|
||||
it('budgets tabs independently', async () => {
|
||||
expect(
|
||||
await requestTerminalPaneRecovery({ tabId: 'tab-1', ptyId: 'pty-1', reason: 'write-stalled' })
|
||||
|
||||
@@ -138,13 +138,18 @@ function scheduleRecoveryRetry(request: RecoveryRequest, delayMs: number): void
|
||||
const timer = setTimeout(
|
||||
() => {
|
||||
pendingRetryByTabId.delete(request.tabId)
|
||||
const currentRequest = [...requestsByInstanceId.values()].find(
|
||||
const currentRequests = [...requestsByInstanceId.values()].filter(
|
||||
isCurrentTerminalRecoveryRequest
|
||||
)
|
||||
if (!currentRequest) {
|
||||
if (currentRequests.length === 0) {
|
||||
return
|
||||
}
|
||||
void requestTerminalPaneRecovery(currentRequest)
|
||||
// Why: one split's liveness probe may fail or never settle while a
|
||||
// sibling has a probe-certified dead renderer. Start every current
|
||||
// request so the first valid remount wins and invalidates the rest.
|
||||
void Promise.all(
|
||||
currentRequests.map((currentRequest) => requestTerminalPaneRecovery(currentRequest))
|
||||
)
|
||||
},
|
||||
Math.max(delayMs, 1_000)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user