fix(desktop): wait 5m before reconnect warning toast
Brief transport blips often self-heal in 1–3 minutes. Raise the non-blocking escalate toast from 45s to 5m so those windows stay quiet while chat remains readable/draftable. Confirmed reauth still takes the full-screen recovery overlay immediately.
This commit is contained in:
@@ -372,8 +372,9 @@ describe('useGatewayBoot remote reconnect loop (real hook, fake socket)', () =>
|
||||
act(() => FakeWebSocket.instances[0].drop())
|
||||
await flushAsync()
|
||||
|
||||
// Walk the backoff past the ~45s escalation threshold.
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
// Walk the backoff well past the historical 45s threshold and into the
|
||||
// current multi-minute escalate window. Chat must stay unlocked either way.
|
||||
for (let i = 0; i < 24; i += 1) {
|
||||
await advanceBackoff()
|
||||
}
|
||||
|
||||
@@ -393,7 +394,7 @@ describe('useGatewayBoot remote reconnect loop (real hook, fake socket)', () =>
|
||||
act(() => FakeWebSocket.instances[0].drop())
|
||||
await flushAsync()
|
||||
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
for (let i = 0; i < 24; i += 1) {
|
||||
await advanceBackoff()
|
||||
}
|
||||
|
||||
|
||||
@@ -64,11 +64,15 @@ import { stashGatewaySurvivor, survivorIsStale, takeGatewaySurvivor } from './ga
|
||||
|
||||
// After the reconnect loop has been failing for this long, raise a NON-blocking
|
||||
// warning toast. Full-screen BootFailureOverlay used to lock the user out of
|
||||
// reading/drafting for the whole 1–3 minute blip even though the transcript is
|
||||
// still on screen underneath. Confirmed reauth still escalates to the overlay
|
||||
// (Sign in is required). Time-based (not attempt-count) because full-jitter
|
||||
// backoff makes attempt counts a meaningless clock.
|
||||
const RECONNECT_ESCALATE_AFTER_MS = 45_000
|
||||
// reading/drafting for the whole blip even though the transcript is still on
|
||||
// screen underneath. Confirmed reauth still escalates to the overlay (Sign in
|
||||
// is required). Time-based (not attempt-count) because full-jitter backoff
|
||||
// makes attempt counts a meaningless clock.
|
||||
//
|
||||
// 5 minutes (not the historical ~45s) so brief transport weather — ticket mint
|
||||
// flaps, sleep/wake, Wi‑Fi blips that self-heal in 1–3 minutes — never even
|
||||
// toast. Chat stays readable/draftable the whole time either way.
|
||||
const RECONNECT_ESCALATE_AFTER_MS = 300_000
|
||||
|
||||
// Bounded self-heal for a failed REMOTE boot (#82679): when the primary boot
|
||||
// fails on a transient remote fault (dropped SSH/HTTP registered connection,
|
||||
@@ -158,9 +162,8 @@ export function useGatewayBoot({
|
||||
// identical error toasts (and their haptics). Reset on the next clean open.
|
||||
let reauthNotified = false
|
||||
// Raised once the reconnect loop has been failing for
|
||||
// RECONNECT_ESCALATE_AFTER_MS so the recovery overlay replaces the
|
||||
// dead-end CONNECTING screen. Reset on a clean open or a manual/
|
||||
// wake-driven reconnect.
|
||||
// RECONNECT_ESCALATE_AFTER_MS so we fire a single non-blocking toast.
|
||||
// Reset on a clean open or a manual/wake-driven reconnect.
|
||||
let escalated = false
|
||||
// Bounded automatic boot retry for transient REMOTE failures (#82679).
|
||||
let bootRetryAttempt = 0
|
||||
|
||||
@@ -170,14 +170,14 @@ describe('connecting overlay vs recovery surface', () => {
|
||||
expect(isRecoveryShown()).toBe(false)
|
||||
})
|
||||
|
||||
it('FIX: once the prolonged reconnect raises a recoverable boot error, the recovery overlay takes over', async () => {
|
||||
// Mirrors what useGatewayBoot.scheduleReconnect() now does after ~45s of
|
||||
// failed post-boot reconnects: it calls failDesktopBoot(), flipping the UI
|
||||
// from the dead-end CONNECTING overlay to the recovery surface.
|
||||
it('FIX: confirmed reauth boot.error still surfaces the recovery overlay (not CONNECTING)', async () => {
|
||||
// Transport blips no longer set boot.error (toast + background retry).
|
||||
// Confirmed OAuth reauth still does — and that recovery surface must win
|
||||
// over any residual connecting state so Sign-in / Gateway settings stay reachable.
|
||||
setGatewayState('error')
|
||||
$desktopBoot.set({
|
||||
...$desktopBoot.get(),
|
||||
error: 'Lost connection to the Hermes gateway and could not reconnect.',
|
||||
error: 'Your remote gateway session has expired. Sign in again.',
|
||||
running: false,
|
||||
visible: true
|
||||
})
|
||||
@@ -191,7 +191,7 @@ describe('connecting overlay vs recovery surface', () => {
|
||||
)
|
||||
})
|
||||
|
||||
// Escape hatch is now reachable; the connecting overlay bows out.
|
||||
// Escape hatch is reachable; the connecting overlay bows out.
|
||||
expect(isRecoveryShown()).toBe(true)
|
||||
expect(screen.getByRole('button', { name: /gateway settings/i })).toBeTruthy()
|
||||
expect(isConnectingShown()).toBe(false)
|
||||
|
||||
Reference in New Issue
Block a user