mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
perf(desktop): persist channel snapshot hash (#5684)
## Summary - persist each relay/identity's complete channel list and server hash as one integrity-checked snapshot - paint the snapshot immediately on cold boot, then revalidate with `knownHash` - fail slow-never-wrong: malformed/legacy/partial snapshots and mismatched not-modified responses force an unhashed full fetch - add sidebar boot diagnostics and deterministic unit/E2E coverage for boot, identity/relay isolation, partial writes, mismatch fallback, and community switches ## Safety invariants - channel list and hash are serialized in one localStorage document and replaced together - snapshot ownership is scoped to normalized relay URL plus identity pubkey - a not-modified response is accepted only when its hash exactly matches the hash describing the available list - any missing or impossible hash/list pairing retries `getChannels(null)` before replacing persistence ## Validation At exact commit `19ca25d23c434cc0b8893a93691aaf4c77794f60` with a clean working tree: - `cd desktop && pnpm check && pnpm typecheck` — passed (existing informational Biome findings only) - `cd desktop && pnpm test` — 4,723 passed - `cd desktop && node --import ./test-loader.mjs --experimental-strip-types --test src/features/channels/channelSnapshot.test.mjs` — 13 passed - `cd desktop && pnpm exec playwright test e2e/sidebar-snapshot.spec.ts --grep "cold boot paints" --repeat-each=5` — 5 passed - `cd desktop && pnpm exec playwright test e2e/sidebar-snapshot.spec.ts` — 8 passed - push hooks repeated desktop check/typecheck and all 4,723 unit tests successfully The Playwright suite uses injected bridge delays. Its roughly 0.5–0.6 s snapshot paint and 3.0 s snapshot-to-live readings are synthetic invariant evidence, not production desktop performance measurements. ## Measurement context The controlled current-main investigation is documented separately in `RESEARCH/DESKTOP_PERF_DEEP_DIVE_2026_08_12.md`; its raw local artifacts are `.scratch/summer-perf-deepdive-results-v2.json`, `.scratch/summer-perf-deepdive-run.log`, `.scratch/summer-perf-deepdive-run-2.log`, and `.scratch/summer-perf-deepdive-build-2.log`. Those original timings are also synthetic Chromium/mock-bridge measurements and are not presented as shipped Tauri/WKWebView or production-relay numbers. ## Latest review delta At exact tip `e8e2b1d617aac7ea008258ad9974bbf8da9cd2eb`, storage-denial reads fail open to the live fetch, hashless retries reject `channels: null` before pair/persistence updates, identity-read failure enables a hashless live fetch, and repeated consumers reuse snapshot parsing/integrity validation by storage key + raw document. The four remaining review nits are deferred as non-blocking follow-ups. Validation at this tip: sidebar snapshot E2E 30/30 serial; desktop unit suite 4,725/4,725; full push gate green (desktop check/typecheck/unit, Rust, Tauri). --------- Signed-off-by: Summer <1fdd3cc104e2911eb3b2da6f97d1b25f4a7f3550ded4492b24ff1d95acd66766@buzz.block.builderlab.xyz> Co-authored-by: Summer <1fdd3cc104e2911eb3b2da6f97d1b25f4a7f3550ded4492b24ff1d95acd66766@buzz.block.builderlab.xyz>
This commit is contained in:
@@ -4,6 +4,11 @@ import { installMockBridge } from "../helpers/bridge";
|
||||
import { FEATURE_OVERRIDES_STORAGE_KEY } from "../helpers/features";
|
||||
|
||||
const RELAY_URL = "ws://localhost:3000";
|
||||
const OWNER_PUBKEY = "deadbeef".repeat(8);
|
||||
|
||||
function snapshotKey(relayUrl: string) {
|
||||
return `buzz-channels.v1:${relayUrl}:${OWNER_PUBKEY.toLowerCase()}`;
|
||||
}
|
||||
|
||||
const COMMUNITY_A = {
|
||||
id: "ws-a",
|
||||
@@ -412,33 +417,36 @@ test.describe("community rail", () => {
|
||||
await seedCommunities(page, [COMMUNITY_A, COMMUNITY_B], COMMUNITY_A.id);
|
||||
await page.goto("/");
|
||||
await expect(page.getByTestId("app-sidebar")).toBeVisible();
|
||||
const rememberedChannelId = await page.evaluate((communityId) => {
|
||||
const source = window.localStorage.getItem(
|
||||
"buzz-channels.v1:ws://localhost:3000",
|
||||
);
|
||||
if (!source) throw new Error("missing source channel snapshot");
|
||||
const snapshot = JSON.parse(source) as {
|
||||
channels: Array<{ id: string; name: string }>;
|
||||
};
|
||||
const generalChannel = snapshot.channels.find(
|
||||
(channel) => channel.name === "general",
|
||||
);
|
||||
if (!generalChannel) throw new Error("missing general channel snapshot");
|
||||
window.localStorage.setItem(
|
||||
"buzz-channels.v1:ws://localhost:3001",
|
||||
source,
|
||||
);
|
||||
window.localStorage.setItem(
|
||||
"buzz-community-destinations",
|
||||
JSON.stringify({
|
||||
[communityId]: {
|
||||
kind: "channel",
|
||||
channelId: generalChannel.id,
|
||||
},
|
||||
}),
|
||||
);
|
||||
return generalChannel.id;
|
||||
}, COMMUNITY_B.id);
|
||||
const rememberedChannelId = await page.evaluate(
|
||||
({ communityId, sourceSnapshotKey, targetSnapshotKey }) => {
|
||||
const source = window.localStorage.getItem(sourceSnapshotKey);
|
||||
if (!source) throw new Error("missing source channel snapshot");
|
||||
const snapshot = JSON.parse(source) as {
|
||||
channels: Array<{ id: string; name: string }>;
|
||||
};
|
||||
const generalChannel = snapshot.channels.find(
|
||||
(channel) => channel.name === "general",
|
||||
);
|
||||
if (!generalChannel)
|
||||
throw new Error("missing general channel snapshot");
|
||||
window.localStorage.setItem(targetSnapshotKey, source);
|
||||
window.localStorage.setItem(
|
||||
"buzz-community-destinations",
|
||||
JSON.stringify({
|
||||
[communityId]: {
|
||||
kind: "channel",
|
||||
channelId: generalChannel.id,
|
||||
},
|
||||
}),
|
||||
);
|
||||
return generalChannel.id;
|
||||
},
|
||||
{
|
||||
communityId: COMMUNITY_B.id,
|
||||
sourceSnapshotKey: snapshotKey(COMMUNITY_A.relayUrl),
|
||||
targetSnapshotKey: snapshotKey(COMMUNITY_B.relayUrl),
|
||||
},
|
||||
);
|
||||
|
||||
await page.evaluate(() => {
|
||||
const testWindow = window as typeof window & {
|
||||
@@ -478,28 +486,29 @@ test.describe("community rail", () => {
|
||||
}, COMMUNITY_B.id);
|
||||
|
||||
await page.goto("/");
|
||||
const sourceSnapshotKey = snapshotKey(COMMUNITY_A.relayUrl);
|
||||
const targetSnapshotKey = snapshotKey(COMMUNITY_B.relayUrl);
|
||||
await expect
|
||||
.poll(() =>
|
||||
page.evaluate(() =>
|
||||
window.localStorage.getItem("buzz-channels.v1:ws://localhost:3000"),
|
||||
page.evaluate(
|
||||
(key) => window.localStorage.getItem(key),
|
||||
sourceSnapshotKey,
|
||||
),
|
||||
)
|
||||
.not.toBeNull();
|
||||
await page.evaluate(() => {
|
||||
const source = window.localStorage.getItem(
|
||||
"buzz-channels.v1:ws://localhost:3000",
|
||||
);
|
||||
if (!source) throw new Error("missing source channel snapshot");
|
||||
const snapshot = JSON.parse(source);
|
||||
snapshot.channels = snapshot.channels.map(
|
||||
(channel: Record<string, unknown>, index: number) =>
|
||||
index === 0 ? { ...channel, id: "missing-channel" } : channel,
|
||||
);
|
||||
window.localStorage.setItem(
|
||||
"buzz-channels.v1:ws://localhost:3001",
|
||||
JSON.stringify(snapshot),
|
||||
);
|
||||
});
|
||||
await page.evaluate(
|
||||
({ sourceKey, targetKey }) => {
|
||||
const source = window.localStorage.getItem(sourceKey);
|
||||
if (!source) throw new Error("missing source channel snapshot");
|
||||
const snapshot = JSON.parse(source);
|
||||
snapshot.channels = snapshot.channels.map(
|
||||
(channel: Record<string, unknown>, index: number) =>
|
||||
index === 0 ? { ...channel, id: "missing-channel" } : channel,
|
||||
);
|
||||
window.localStorage.setItem(targetKey, JSON.stringify(snapshot));
|
||||
},
|
||||
{ sourceKey: sourceSnapshotKey, targetKey: targetSnapshotKey },
|
||||
);
|
||||
await page.getByTestId(`community-rail-button-${COMMUNITY_B.id}`).click();
|
||||
|
||||
await expect(page).not.toHaveURL(/#\/channels\//);
|
||||
@@ -531,10 +540,12 @@ test.describe("community rail", () => {
|
||||
}, COMMUNITY_B.id);
|
||||
await page.goto("/");
|
||||
await expect(page.getByTestId("app-sidebar")).toBeVisible();
|
||||
const sourceSnapshotKey = snapshotKey(COMMUNITY_A.relayUrl);
|
||||
await expect
|
||||
.poll(() =>
|
||||
page.evaluate(() =>
|
||||
window.localStorage.getItem("buzz-channels.v1:ws://localhost:3000"),
|
||||
page.evaluate(
|
||||
(key) => window.localStorage.getItem(key),
|
||||
sourceSnapshotKey,
|
||||
),
|
||||
)
|
||||
.not.toBeNull();
|
||||
@@ -563,20 +574,21 @@ test.describe("community rail", () => {
|
||||
};
|
||||
}),
|
||||
).toEqual({ released: 0, pending: 0 });
|
||||
await page.evaluate(() => {
|
||||
const source = window.localStorage.getItem(
|
||||
"buzz-channels.v1:ws://localhost:3000",
|
||||
);
|
||||
if (!source) throw new Error("missing source channel snapshot");
|
||||
const snapshot = JSON.parse(source);
|
||||
snapshot.channels = snapshot.channels.filter(
|
||||
(channel: { id: string }) => channel.id !== "general",
|
||||
);
|
||||
window.localStorage.setItem(
|
||||
"buzz-channels.v1:ws://localhost:3001",
|
||||
JSON.stringify(snapshot),
|
||||
);
|
||||
});
|
||||
await page.evaluate(
|
||||
({ sourceKey, targetKey }) => {
|
||||
const source = window.localStorage.getItem(sourceKey);
|
||||
if (!source) throw new Error("missing source channel snapshot");
|
||||
const snapshot = JSON.parse(source);
|
||||
snapshot.channels = snapshot.channels.filter(
|
||||
(channel: { id: string }) => channel.id !== "general",
|
||||
);
|
||||
window.localStorage.setItem(targetKey, JSON.stringify(snapshot));
|
||||
},
|
||||
{
|
||||
sourceKey: sourceSnapshotKey,
|
||||
targetKey: snapshotKey(COMMUNITY_B.relayUrl),
|
||||
},
|
||||
);
|
||||
await page.evaluate(() => {
|
||||
const config = (
|
||||
window as Window & {
|
||||
|
||||
Reference in New Issue
Block a user