Private
Public Access
Harden the update-check pipeline against silent failures (#58)
checkForUpdate() was a bare `void registration?.update()` -- a failed fetch (most plausible right when it's triggered by a WS reconnect, i.e. the network just flapped from a backend restart) vanished with nothing caught or logged, leaving only the hourly interval as a fallback. Now logs the failure instead of swallowing it, and a third trigger checks for an update whenever a backgrounded tab becomes visible again, so a tab that misses both the reconnect-triggered check and the hourly timer still gets a chance the moment someone actually looks at it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { useEffect } from 'react'
|
||||||
import { useRegisterSW } from 'virtual:pwa-register/react'
|
import { useRegisterSW } from 'virtual:pwa-register/react'
|
||||||
import { checkForUpdate, setSwRegistration } from '../lib/swUpdate'
|
import { checkForUpdate, setSwRegistration } from '../lib/swUpdate'
|
||||||
import './UpdateBanner.css'
|
import './UpdateBanner.css'
|
||||||
@@ -26,6 +27,21 @@ export function UpdateBanner() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// #58: a third trigger, alongside WS-reconnect and the hourly interval
|
||||||
|
// above -- a tab backgrounded across a deploy gets checked the moment
|
||||||
|
// someone actually looks at it again, rather than waiting on whichever
|
||||||
|
// of those two happens to land first. Cheap insurance against either
|
||||||
|
// one missing its moment (e.g. the reconnect-triggered check landing
|
||||||
|
// during the same network blip that caused the reconnect, and failing
|
||||||
|
// -- see checkForUpdate's own comment).
|
||||||
|
function handleVisibilityChange() {
|
||||||
|
if (document.visibilityState === 'visible') checkForUpdate()
|
||||||
|
}
|
||||||
|
document.addEventListener('visibilitychange', handleVisibilityChange)
|
||||||
|
return () => document.removeEventListener('visibilitychange', handleVisibilityChange)
|
||||||
|
}, [])
|
||||||
|
|
||||||
if (!needRefresh) return null
|
if (!needRefresh) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -10,5 +10,15 @@ export function setSwRegistration(reg: ServiceWorkerRegistration): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function checkForUpdate(): void {
|
export function checkForUpdate(): void {
|
||||||
void registration?.update()
|
// #58: this used to be a bare `void registration?.update()` -- if the
|
||||||
|
// fetch failed (most plausible right when it's triggered by a WS
|
||||||
|
// reconnect, i.e. the network just flapped from a backend restart), the
|
||||||
|
// rejection vanished with nothing to catch it and nothing logged. The
|
||||||
|
// only other trigger was an hourly interval, so a client that hit this
|
||||||
|
// at the wrong moment could sit stale for up to an hour with zero trace
|
||||||
|
// of why. This doesn't fix a bad network, but it stops the failure from
|
||||||
|
// being silent, and callers still don't need to handle anything.
|
||||||
|
registration?.update().catch((err: unknown) => {
|
||||||
|
console.error('Service worker update check failed', err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user