From 9b6020f76102e51ba2bec07dbdbbcc6a2087a8f9 Mon Sep 17 00:00:00 2001 From: yilsem Date: Sat, 5 Sep 2026 13:50:35 +0300 Subject: [PATCH] fix(desktop): retain cold-start budget after runtime installation --- apps/desktop/src/lib/with-timeout.test.ts | 19 +++++++++++++++++++ apps/desktop/src/lib/with-timeout.ts | 13 +++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src/lib/with-timeout.test.ts b/apps/desktop/src/lib/with-timeout.test.ts index 077ea02..624aae2 100644 --- a/apps/desktop/src/lib/with-timeout.test.ts +++ b/apps/desktop/src/lib/with-timeout.test.ts @@ -3,6 +3,25 @@ import { describe, expect, it, vi } from 'vitest' import { withBootstrapAwareTimeout, withTimeout } from './with-timeout' describe('withTimeout', () => { + it('allows a full cold start when installation finishes near a deadline', async () => { + vi.useFakeTimers() + try { + let active = true + let finish!: (value: string) => void + const connection = new Promise(resolve => { + finish = resolve + }) + const result = withBootstrapAwareTimeout(connection, 45_000, 'timeout', async () => ({ active })) + await vi.advanceTimersByTimeAsync(75_000) + active = false + await vi.advanceTimersByTimeAsync(25_000) + finish('connected') + await expect(result).resolves.toBe('connected') + } finally { + vi.useRealTimers() + } + }) + it.each([{ active: true }, { setupChoice: { active: true } }])( 'waits beyond cold boot during setup: %j', async state => { diff --git a/apps/desktop/src/lib/with-timeout.ts b/apps/desktop/src/lib/with-timeout.ts index 7f82ed6..d12eacc 100644 --- a/apps/desktop/src/lib/with-timeout.ts +++ b/apps/desktop/src/lib/with-timeout.ts @@ -39,6 +39,7 @@ export async function withBootstrapAwareTimeout( cancelled: () => boolean = () => false ): Promise { let settled = false + let setupObserved = false const request = promise.then( value => { settled = true @@ -58,9 +59,17 @@ export async function withBootstrapAwareTimeout( throw error } const state = await withTimeout(bootstrapState(), Math.min(ms, 5_000), message) - if (!state?.active && !state?.setupChoice) { - throw error + if (state?.active || state?.setupChoice) { + setupObserved = true + continue } + // Setup may have finished just before this probe. The new backend must + // still receive one complete cold-start budget after the installer. + if (setupObserved) { + setupObserved = false + continue + } + throw error } } }