Improve app startup and route fallbacks

This commit is contained in:
shuaiplus
2026-05-04 04:19:02 +08:00
parent 45f0387526
commit 75a6a593dc
14 changed files with 858 additions and 87 deletions
+56 -26
View File
@@ -16,6 +16,15 @@ function normalizeSnapshot(body: VaultSyncResponse | null | undefined): VaultCor
return {
ciphers: Array.isArray(body?.ciphers) ? body!.ciphers! : [],
folders: Array.isArray(body?.folders) ? body!.folders! : [],
sends: Array.isArray(body?.sends) ? body!.sends! : [],
};
}
function normalizeCachedSnapshot(snapshot: Partial<VaultCoreSnapshot> | null | undefined): VaultCoreSnapshot {
return {
ciphers: Array.isArray(snapshot?.ciphers) ? snapshot.ciphers : [],
folders: Array.isArray(snapshot?.folders) ? snapshot.folders : [],
sends: Array.isArray(snapshot?.sends) ? snapshot.sends : [],
};
}
@@ -26,49 +35,70 @@ export async function getCachedVaultCoreSnapshot(cacheKey: string): Promise<Vaul
if (memory) return memory.snapshot;
const cached = await loadCachedVaultCoreSnapshot(normalizedKey);
if (!cached?.snapshot) return null;
const snapshot = normalizeCachedSnapshot(cached.snapshot);
memoryVaultCoreCache.set(normalizedKey, {
revisionStamp: cached.revisionStamp,
snapshot: cached.snapshot,
snapshot,
});
return cached.snapshot;
return snapshot;
}
export async function loadVaultCoreSyncSnapshot(authedFetch: AuthedFetch, cacheKey: string): Promise<VaultCoreSnapshot> {
const normalizedKey = String(cacheKey || '').trim();
if (!normalizedKey) return { ciphers: [], folders: [] };
if (!normalizedKey) return { ciphers: [], folders: [], sends: [] };
const existing = pendingVaultCoreRequests.get(normalizedKey);
if (existing) return existing;
const request = (async () => {
const revisionStamp = await getVaultRevisionDate(authedFetch);
const memory = memoryVaultCoreCache.get(normalizedKey);
if (memory?.revisionStamp === revisionStamp) {
return memory.snapshot;
}
const cached = await loadCachedVaultCoreSnapshot(normalizedKey);
if (cached?.revisionStamp === revisionStamp && cached.snapshot) {
let cached = await loadCachedVaultCoreSnapshot(normalizedKey);
if (!memory && cached?.snapshot) {
const snapshot = normalizeCachedSnapshot(cached.snapshot);
memoryVaultCoreCache.set(normalizedKey, {
revisionStamp,
snapshot: cached.snapshot,
revisionStamp: cached.revisionStamp,
snapshot,
});
return cached.snapshot;
}
const resp = await authedFetch('/api/sync?excludeSends=true&excludeDomains=true', {
cache: 'no-store',
headers: {
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
},
});
if (!resp.ok) throw new Error('Failed to load vault');
const body = await parseJson<VaultSyncResponse>(resp);
const snapshot = normalizeSnapshot(body);
memoryVaultCoreCache.set(normalizedKey, { revisionStamp, snapshot });
void saveCachedVaultCoreSnapshot(normalizedKey, revisionStamp, snapshot);
return snapshot;
try {
const revisionStamp = await getVaultRevisionDate(authedFetch);
const currentMemory = memoryVaultCoreCache.get(normalizedKey);
if (currentMemory?.revisionStamp === revisionStamp) {
return currentMemory.snapshot;
}
if (!cached) {
cached = await loadCachedVaultCoreSnapshot(normalizedKey);
}
if (cached?.revisionStamp === revisionStamp && cached.snapshot) {
const snapshot = normalizeCachedSnapshot(cached.snapshot);
memoryVaultCoreCache.set(normalizedKey, {
revisionStamp,
snapshot,
});
return snapshot;
}
const resp = await authedFetch('/api/sync', {
cache: 'no-store',
headers: {
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
},
});
if (!resp.ok) throw new Error('Failed to load vault');
const body = await parseJson<VaultSyncResponse>(resp);
const snapshot = normalizeSnapshot(body);
memoryVaultCoreCache.set(normalizedKey, { revisionStamp, snapshot });
void saveCachedVaultCoreSnapshot(normalizedKey, revisionStamp, snapshot);
return snapshot;
} catch (error) {
const fallbackMemory = memoryVaultCoreCache.get(normalizedKey);
if (fallbackMemory?.snapshot) return fallbackMemory.snapshot;
if (cached?.snapshot) return normalizeCachedSnapshot(cached.snapshot);
throw error;
}
})();
pendingVaultCoreRequests.set(normalizedKey, request);