diff --git a/src/service-worker.ts b/src/service-worker.ts index ee3a14e..0bbc7e4 100644 --- a/src/service-worker.ts +++ b/src/service-worker.ts @@ -117,10 +117,12 @@ async function runSync(isUpdate: boolean): Promise { await broadcast({ type: 'sync-start', total: worklist.length }); + const successful = new Set(); let done = 0; const tasks = worklist.map((id) => async () => { const summary = summaries.find((s) => s.id === id); - await cacheRecipe(id, summary?.image_path ?? null); + const ok = await cacheRecipe(id, summary?.image_path ?? null); + if (ok) successful.add(id); done += 1; await broadcast({ type: 'sync-progress', current: done, total: worklist.length }); }); @@ -130,7 +132,15 @@ async function runSync(isUpdate: boolean): Promise { await removeRecipes(toRemove); } - await saveCachedIds(currentIds); + // Manifest: für Update = (cached - toRemove) + neue successes + // Für Initial = nur die diesmal erfolgreich gecachten + const finalManifest = isUpdate + ? Array.from( + new Set([...cachedIds.filter((id) => !toRemove.includes(id)), ...successful]) + ) + : Array.from(successful); + + await saveCachedIds(finalManifest); await broadcast({ type: 'sync-done', lastSynced: Date.now() }); } catch (e) { await broadcast({ @@ -154,24 +164,33 @@ async function fetchAllSummaries(): Promise { return result; } -async function cacheRecipe(id: number, imagePath: string | null): Promise { +async function cacheRecipe(id: number, imagePath: string | null): Promise { const data = await caches.open(DATA_CACHE); const images = await caches.open(IMAGES_CACHE); - await Promise.all([ + const [htmlOk, apiOk] = await Promise.all([ addToCache(data, `/recipes/${id}`), - addToCache(data, `/api/recipes/${id}`), - imagePath && !/^https?:\/\//i.test(imagePath) - ? addToCache(images, `/images/${imagePath}`) - : Promise.resolve() + addToCache(data, `/api/recipes/${id}`) ]); + if (imagePath && !/^https?:\/\//i.test(imagePath)) { + // Image-Fehler soll den Recipe-Eintrag nicht invalidieren (bei + // manchen Rezepten gibt es schlicht kein Bild) + await addToCache(images, `/images/${imagePath}`); + } + return htmlOk && apiOk; } -async function addToCache(cache: Cache, url: string): Promise { +async function addToCache(cache: Cache, url: string): Promise { try { const res = await fetch(url); - if (res.ok) await cache.put(url, res); - } catch { - // Einzelne Fehler ignorieren — nächster Sync holt's nach. + if (!res.ok) { + console.warn(`[sw] cache miss ${url}: HTTP ${res.status}`); + return false; + } + await cache.put(url, res); + return true; + } catch (e) { + console.warn(`[sw] cache error ${url}:`, e); + return false; } }