From c8ee4be34fed054f626007b88fe866fd09e2457e Mon Sep 17 00:00:00 2001 From: "nekomimi.pet" Date: Wed, 7 Oct 2026 20:09:08 -0400 Subject: [PATCH] fix(dashboard): keep waiting on the site list for a minute, not 28 s firehose-service has taken up to 43 s from receiving a deploy to listing it (VictoriaLogs, n=18, p90 10.9 s). With a 28 s window a new site's deploying row vanished before it was listed. After the 1..7 s steps the dashboard now keeps checking every 8 s, up to 60 s in all. --- apps/main-app/public/editor/queries.test.ts | 23 ++++++++++++++++--- apps/main-app/public/editor/queries.ts | 4 ++-- apps/main-app/public/editor/site-sync.test.ts | 6 ++--- apps/main-app/public/editor/site-sync.ts | 7 ++++-- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/apps/main-app/public/editor/queries.test.ts b/apps/main-app/public/editor/queries.test.ts index 0d76f50..b48ad73 100644 --- a/apps/main-app/public/editor/queries.test.ts +++ b/apps/main-app/public/editor/queries.test.ts @@ -81,16 +81,18 @@ describe('site list after a delete', () => { expect(noticeStore.get()).toBeNull() }) - test('gives up after half a minute and shows what the server lists, with a notice', async () => { + test('gives up after a minute and shows what the server lists, with a notice', async () => { let finished = false void expectSiteChange({ kind: 'deleted', key: 'public:blog', name: 'blog' }).then(() => { finished = true }) await flush() - for (let second = 0; second < 28; second++) await advance(1000) + for (let second = 0; second < 59; second++) await advance(1000) + expect(finished).toBe(false) + await advance(1000) expect(finished).toBe(true) expect(cached()).toEqual(['blog', 'zine']) - expect(siteRequests()).toHaveLength(8) + expect(siteRequests()).toHaveLength(12) expect(noticeStore.get()?.text).toContain('blog') }) }) @@ -112,6 +114,21 @@ describe('site list after a deploy', () => { expect(deploying()).not.toHaveProperty('deploying') }) + test('keeps a new site listed through a 43 s firehose lag', async () => { + const done = expectSiteChange({ kind: 'deployed', rkey: 'slow', cid: 'cid-slow', at: Date.now() }) + const slow = () => queryClient.getQueryData(keys.sites)?.find((site) => site.name === 'slow') + await flush() + for (let second = 0; second < 43; second++) { + await advance(1000) + expect(slow()).toMatchObject({ deploying: true }) + } + listed = [record('slow', 'cid-slow'), ...listed] + await advance(1000) + await done + expect(slow()).toMatchObject({ recordCid: 'cid-slow' }) + expect(noticeStore.get()).toBeNull() + }) + test('waits for the new record when the server still has the old one', async () => { const done = expectSiteChange({ kind: 'deployed', rkey: 'blog', cid: 'cid-blog-2', at: Date.now() }) const blog = () => queryClient.getQueryData(keys.sites)?.find((site) => site.name === 'blog') diff --git a/apps/main-app/public/editor/queries.ts b/apps/main-app/public/editor/queries.ts index 6edf4ad..f056871 100644 --- a/apps/main-app/public/editor/queries.ts +++ b/apps/main-app/public/editor/queries.ts @@ -57,8 +57,8 @@ async function fetchSites(): Promise { /** * Shows a deploy or delete in the site list at once, then refetches on a short - * backoff until the server list shows it too. If it has not after half a minute - * the list goes back to what the server says. + * backoff until the server list shows it too. If it has not after a minute the + * list goes back to what the server says. */ export async function expectSiteChange(change: SiteChange): Promise { waitingChanges = [...waitingChanges, change] diff --git a/apps/main-app/public/editor/site-sync.test.ts b/apps/main-app/public/editor/site-sync.test.ts index 987555d..a0fe27b 100644 --- a/apps/main-app/public/editor/site-sync.test.ts +++ b/apps/main-app/public/editor/site-sync.test.ts @@ -99,7 +99,7 @@ describe('waitUntilSettled', () => { expect(checks).toHaveLength(2) }) - test('gives up after 28 s instead of looping forever', async () => { + test('gives up after 60 s instead of looping forever', async () => { let checks = 0 let result: boolean | undefined void waitUntilSettled(async () => { @@ -108,7 +108,7 @@ describe('waitUntilSettled', () => { }).then((settled) => { result = settled }) - for (let second = 0; second < 27; second++) { + for (let second = 0; second < 59; second++) { jest.advanceTimersByTime(1000) await flush() } @@ -116,6 +116,6 @@ describe('waitUntilSettled', () => { jest.advanceTimersByTime(1000) await flush() expect(result).toBe(false) - expect(checks).toBe(7) + expect(checks).toBe(11) }) }) diff --git a/apps/main-app/public/editor/site-sync.ts b/apps/main-app/public/editor/site-sync.ts index a6a51e4..9a9884a 100644 --- a/apps/main-app/public/editor/site-sync.ts +++ b/apps/main-app/public/editor/site-sync.ts @@ -52,8 +52,11 @@ export function deployedChange(result: UploadResult, at: number): SiteChange | n return rkey && result.cid ? { kind: 'deployed', rkey, cid: result.cid, at } : null } -/** Pauses between refetches while a change is on its way: 28 s in all, then the list is left to the server. */ -export const SETTLE_DELAYS_MS: readonly number[] = [1000, 2000, 3000, 4000, 5000, 6000, 7000] +/** + * Pauses between refetches while a change is on its way: 60 s in all, then the list is left to the + * server. The firehose has been seen taking 43 s to list a deploy, so the tail keeps checking every 8 s. + */ +export const SETTLE_DELAYS_MS: readonly number[] = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 8000, 8000, 8000] const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) -- 2.54.0