fix(desktop): close the backend update overlay on success; error on no-return
Three rough edges in the remote backend apply flow: - On success the overlay dropped to IDLE, briefly re-rendering the pre-install 'update available' view and then the generic 'you're all set' before settling. Close the overlay outright once the backend is confirmed back instead of bouncing through the idle view. - If the backend never came back (a failed restart), the flow still reported success. waitForBackendReturn now returns whether the backend answered; finishBackendApply surfaces an error when it didn't. - The up-to-date copy said 'you're running the latest version', conflating client and backend. Backend target now reads 'the backend is running the latest version' — the client's own version is a separate pill.
This commit is contained in:
@@ -182,5 +182,18 @@ describe('applyBackendUpdate recovery', () => {
|
||||
expect($backendUpdateApply.get().stage).toBe('idle')
|
||||
expect($backendUpdateApply.get().applying).toBe(false)
|
||||
})
|
||||
|
||||
it('surfaces an error when the backend never comes back after the restart', async () => {
|
||||
updateHermesSpy.mockResolvedValue({ ok: true, name: 'update', pid: 1 })
|
||||
getActionStatusSpy.mockRejectedValue(new Error('ECONNREFUSED'))
|
||||
checkHermesUpdateSpy.mockRejectedValue(new Error('ECONNREFUSED'))
|
||||
|
||||
const promise = applyBackendUpdate()
|
||||
await vi.advanceTimersByTimeAsync(70000)
|
||||
const result = await promise
|
||||
|
||||
expect(result.ok).toBe(false)
|
||||
expect($backendUpdateApply.get().stage).toBe('error')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -307,17 +307,39 @@ export async function applyUpdates(opts: DesktopUpdateApplyOptions = {}): Promis
|
||||
const BACKEND_RETURN_POLL_MS = 1500
|
||||
const BACKEND_RETURN_MAX_ATTEMPTS = 40
|
||||
|
||||
async function waitForBackendReturn(): Promise<void> {
|
||||
async function waitForBackendReturn(): Promise<boolean> {
|
||||
for (let attempt = 0; attempt < BACKEND_RETURN_MAX_ATTEMPTS; attempt += 1) {
|
||||
await new Promise(resolve => globalThis.setTimeout(resolve, BACKEND_RETURN_POLL_MS))
|
||||
try {
|
||||
await checkHermesUpdate()
|
||||
|
||||
return
|
||||
return true
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function finishBackendApply(returned: boolean): DesktopUpdateApplyResult {
|
||||
if (returned) {
|
||||
$backendUpdateApply.set(IDLE)
|
||||
setUpdateOverlayOpen(false)
|
||||
void checkBackendUpdates()
|
||||
|
||||
return { ok: true, message: 'Backend update applied.' }
|
||||
}
|
||||
|
||||
$backendUpdateApply.set({
|
||||
...$backendUpdateApply.get(),
|
||||
applying: false,
|
||||
stage: 'error',
|
||||
error: 'apply-failed',
|
||||
message: 'Backend updated but did not come back online. Check the backend host.'
|
||||
})
|
||||
|
||||
return { ok: false, error: 'apply-failed', message: 'Backend did not come back online.' }
|
||||
}
|
||||
|
||||
export async function applyBackendUpdate(): Promise<DesktopUpdateApplyResult> {
|
||||
@@ -350,11 +372,8 @@ export async function applyBackendUpdate(): Promise<DesktopUpdateApplyResult> {
|
||||
stage: 'restart',
|
||||
message: 'Backend restarting to load the update…'
|
||||
})
|
||||
await waitForBackendReturn()
|
||||
$backendUpdateApply.set(IDLE)
|
||||
void checkBackendUpdates()
|
||||
|
||||
return { ok: true, message: 'Backend update applied; backend is back online.' }
|
||||
return finishBackendApply(await waitForBackendReturn())
|
||||
}
|
||||
|
||||
if (last && !last.running) {
|
||||
@@ -365,11 +384,8 @@ export async function applyBackendUpdate(): Promise<DesktopUpdateApplyResult> {
|
||||
const ok = !!last && (last.exit_code ?? 1) === 0
|
||||
if (ok) {
|
||||
$backendUpdateApply.set({ ...$backendUpdateApply.get(), applying: true, stage: 'restart', message: 'Backend restarting to load the update…' })
|
||||
await waitForBackendReturn()
|
||||
$backendUpdateApply.set(IDLE)
|
||||
void checkBackendUpdates()
|
||||
|
||||
return { ok: true, message: 'Backend update applied.' }
|
||||
return finishBackendApply(await waitForBackendReturn())
|
||||
}
|
||||
|
||||
$backendUpdateApply.set({
|
||||
|
||||
Reference in New Issue
Block a user