aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-03-28 06:27:53 +0000
committerFuwn <[email protected]>2026-03-28 06:27:53 +0000
commitbfe3847ef88405fcb5d08d7134f9db2c9d53e7ef (patch)
treefad84026a509427197fcde50a1d5285aebb65338 /src
parentfix(cache): keep pre-hydration state changes (diff)
downloaddue.moe-bfe3847ef88405fcb5d08d7134f9db2c9d53e7ef.tar.xz
due.moe-bfe3847ef88405fcb5d08d7134f9db2c9d53e7ef.zip
fix(manga): avoid poisoning native chapter cache
Diffstat (limited to 'src')
-rw-r--r--src/lib/Media/Manga/chapters.ts44
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);
}