fix(offline): surface degraded/missing preloads, join re-entrant runs, cache manifest to IDB

- loadManifest() goes through DataCache.fetchWithFallback: the file list is
  written to IDB and survives SW-cache eviction; a run with the reduced
  fallback set is flagged and shown as degraded (new i18n en/ru/cu).
- 404 answers are counted as 'missing' (deployment drift) with a
  preload-missing diag entry, instead of silently reporting Done.
- preload() is re-entrancy safe: concurrent calls join the in-flight run.
- versions.json is loaded once per session (was fetched per translation).
- Write-through failures in fetchWithFallback()/fetch() log idb-write-fail.
- preload-manifest.json SW route is NetworkFirst (fresh coverage online).
- Manifest now also covers the shared/lives + shared/commands fallbacks.
This commit is contained in:
catarrh committed 2026-10-04 17:14:33 +03:00
1 parent 1201e16d5e
commit 8c442bf7b6
7 files changed
+184 -55

No files matched your search

+15
View File
@@ -48,6 +48,21 @@ function calendarFiles(lang: string): string[] {
if (exists(f)) files.push(`/data${f}`);
}
// Shared fallback lives/commands — normally served per-language, but the
// runtime chain ends with a 'shared' attempt; keep those copies offline too.
for (const sub of ['lives', 'commands']) {
const subDir = path.join(DATA_DIR, 'shared', sub);
if (!fs.existsSync(subDir)) continue;
const walkShared = (d: string, rel: string): void => {
for (const e of fs.readdirSync(d, { withFileTypes: true })) {
const p = path.join(d, e.name);
if (e.isDirectory()) walkShared(p, `${rel}/${e.name}`);
else if (e.name.endsWith('.json')) files.push(`/data/shared/${sub}${rel}/${e.name}`);
}
};
walkShared(subDir, '');
}
// Menaion bundle
const mb = `/${lang}/menaion-bundle.json`;
if (exists(mb)) files.push(`/data${mb}`);