mirror of
https://github.com/block/buzz.git
synced 2026-11-01 23:11:58 +00:00
Preserve community data on onboarding write failure
Co-authored-by: npub1cl47vfhsqpqy9pwndphpm36vcp7vvz5h2js4qpqm5yewzj7nutkq7xyw8c <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> Signed-off-by: npub1cl47vfhsqpqy9pwndphpm36vcp7vvz5h2js4qpqm5yewzj7nutkq7xyw8c <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
This commit is contained in:
parent
dc8d7b824f
commit
a57ed65d3b
@@ -3,6 +3,7 @@ import test from "node:test";
|
||||
|
||||
import {
|
||||
clearCommunityStorage,
|
||||
initFirstCommunity,
|
||||
migrateLegacyCommunityStorage,
|
||||
shouldAutoConnectDefaultRelay,
|
||||
} from "./communityStorage.ts";
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
function createMemoryStorage(initial = {}) {
|
||||
const values = new Map(Object.entries(initial));
|
||||
return {
|
||||
values,
|
||||
getItem: (key) => values.get(key) ?? null,
|
||||
setItem: (key, value) => values.set(key, String(value)),
|
||||
removeItem: (key) => values.delete(key),
|
||||
@@ -59,6 +61,28 @@ test("signed-build relay defaults auto-connect during first-run onboarding", ()
|
||||
assert.equal(shouldAutoConnectDefaultRelay("not a valid relay"), false);
|
||||
});
|
||||
|
||||
test("failed first-community write preserves existing community data", () => {
|
||||
const storage = createMemoryStorage({
|
||||
"buzz-communities": '[{"id":"existing"}]',
|
||||
"buzz-workspaces": '[{"id":"legacy"}]',
|
||||
"buzz-active-workspace-id": "legacy",
|
||||
});
|
||||
storage.setItem = (key, value) => {
|
||||
if (key === "buzz-communities") {
|
||||
throw new Error("QuotaExceededError");
|
||||
}
|
||||
storage.values.set(key, String(value));
|
||||
};
|
||||
globalThis.localStorage = storage;
|
||||
globalThis.window = { localStorage: storage };
|
||||
|
||||
assert.equal(initFirstCommunity("wss://relay.example.com", "pubkey"), null);
|
||||
assert.equal(storage.getItem("buzz-communities"), '[{"id":"existing"}]');
|
||||
assert.equal(storage.getItem("buzz-active-community-id"), null);
|
||||
assert.equal(storage.getItem("buzz-workspaces"), '[{"id":"legacy"}]');
|
||||
assert.equal(storage.getItem("buzz-active-workspace-id"), "legacy");
|
||||
});
|
||||
|
||||
test("clearCommunityStorage removes new and legacy state", () => {
|
||||
const storage = createMemoryStorage({
|
||||
"buzz-communities": "new",
|
||||
|
||||
@@ -160,14 +160,26 @@ export function initFirstCommunity(
|
||||
pubkey,
|
||||
addedAt: new Date().toISOString(),
|
||||
};
|
||||
const didSaveCommunities = saveCommunities([community]);
|
||||
const didSaveActiveCommunity =
|
||||
didSaveCommunities && saveActiveCommunityId(community.id);
|
||||
const previousActiveCommunityId = localStorage.getItem(ACTIVE_COMMUNITY_KEY);
|
||||
const didSaveActiveCommunity = saveActiveCommunityId(community.id);
|
||||
if (!didSaveActiveCommunity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// The quota-recovery helper reports failure instead of throwing. Do not let
|
||||
// callers reload unless both writes landed; otherwise first launch can loop.
|
||||
if (!didSaveCommunities || !didSaveActiveCommunity) {
|
||||
clearCommunityStorage();
|
||||
if (!saveCommunities([community])) {
|
||||
// A failed setItem leaves the existing communities value untouched. Roll
|
||||
// back only the active-ID write so inconsistent pre-existing data is never
|
||||
// destroyed while recovering from a quota failure.
|
||||
try {
|
||||
if (previousActiveCommunityId === null) {
|
||||
localStorage.removeItem(ACTIVE_COMMUNITY_KEY);
|
||||
} else {
|
||||
localStorage.setItem(ACTIVE_COMMUNITY_KEY, previousActiveCommunityId);
|
||||
}
|
||||
} catch {
|
||||
// Best effort: persistence is already unavailable, and callers will stay
|
||||
// on setup instead of reloading.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user