diff options
| author | Fuwn <[email protected]> | 2026-03-28 06:27:53 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-03-28 06:27:53 +0000 |
| commit | bfe3847ef88405fcb5d08d7134f9db2c9d53e7ef (patch) | |
| tree | fad84026a509427197fcde50a1d5285aebb65338 /src/lib | |
| parent | fix(cache): keep pre-hydration state changes (diff) | |
| download | due.moe-bfe3847ef88405fcb5d08d7134f9db2c9d53e7ef.tar.xz due.moe-bfe3847ef88405fcb5d08d7134f9db2c9d53e7ef.zip | |
fix(manga): avoid poisoning native chapter cache
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/Media/Manga/chapters.ts | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/src/lib/Media/Manga/chapters.ts b/src/lib/Media/Manga/chapters.ts index a578137a..ff861609 100644 --- a/src/lib/Media/Manga/chapters.ts +++ b/src/lib/Media/Manga/chapters.ts @@ -42,7 +42,10 @@ const parseOptionalNumber = (value: string | number | null | undefined) => { const sleep = (milliseconds: number) => new Promise((resolve) => setTimeout(resolve, milliseconds)); -const readCachedChapterCount = async (mangaId: number) => { +const readCachedChapterCount = async ( + mangaId: number, + allowNullCache = true, +) => { if (chapterMemoryCache.has(mangaId)) return chapterMemoryCache.get(mangaId); if (browserChapterCacheDisabled()) return undefined; @@ -52,7 +55,9 @@ const readCachedChapterCount = async (mangaId: number) => { return chapter === undefined ? undefined : chapter.chapters === -1 - ? null + ? allowNullCache + ? null + : undefined : chapter.chapters; }; @@ -192,6 +197,7 @@ const fetchMangaChapterCounts = async (manga: Media[]) => { const fetchNativeChapterCounts = async (manga: Media[]) => { const data: Record<string, NativeChapterCount> = {}; + const failedIds = new Set<number>(); for (let index = 0; index < manga.length; index += 100) { const chunk = manga.slice(index, index + 100); @@ -210,14 +216,21 @@ const fetchNativeChapterCounts = async (manga: Media[]) => { }), }).catch(() => null); - if (!response?.ok) continue; + if (!response?.ok) { + for (const entry of chunk) failedIds.add(entry.id); + + continue; + } const payload = (await response.json()) as NativeChapterCountsResponse; Object.assign(data, payload.data || {}); + + for (const entry of chunk) + if (!(String(entry.id) in (payload.data || {}))) failedIds.add(entry.id); } - return data; + return { data, failedIds }; }; export const hydrateChapterCounts = async ( @@ -233,7 +246,13 @@ export const hydrateChapterCounts = async ( const unresolvedManga: Media[] = []; for (const entry of uniqueManga) { - if ((await readCachedChapterCount(entry.id)) !== undefined) continue; + if ( + (await readCachedChapterCount( + entry.id, + !settings.get().calculatePreferNativeChapterCount, + )) !== undefined + ) + continue; if (entry.format === "NOVEL") { await getActivityChapterCount(identity, entry, disableGuessing); @@ -251,10 +270,21 @@ export const hydrateChapterCounts = async ( } if (nativeCountManga.length) { - const nativeCounts = await fetchNativeChapterCounts(nativeCountManga); + const { data: nativeCounts, failedIds } = + await fetchNativeChapterCounts(nativeCountManga); for (const entry of nativeCountManga) { - const nativeCount = nativeCounts[String(entry.id)]?.chapter ?? null; + if (failedIds.has(entry.id)) continue; + + const nativeCount = nativeCounts[String(entry.id)]?.chapter; + + if (nativeCount === null) { + unresolvedManga.push(entry); + + continue; + } + + if (nativeCount === undefined) continue; await writeCachedChapterCount(entry.id, nativeCount); } |