Fix IndexedDB cache being defeated when mtime is unparseable (AI)

resolveStub() required a non-null mtime to reuse a cached hydrated
entry, so any listing without a parseable mtime (HTML-autoindex
fallback edge cases) rebuilt every stub from scratch on every crawl.
Comparing mtime directly (including null === null) trusts the cache
when there's no evidence either way, same as before this changed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
biosiasandClaude Sonnet 5 committed 2026-09-22 16:02:31 +02:00
1 parent c8464398b9
commit ae9bcfec3a
1 file changed
+9 -2
+9 -2
View File
@@ -217,11 +217,18 @@ function normalizeMtime(mtime) {
// string. `cacheSnapshot` is the whole cache read once up front (see
// runCrawl) — an in-memory lookup here instead of a separate IndexedDB read
// per file, which mattered when this also had to guard a listing fetch;
// kept anyway since it's still the same one cheap lookup.
// kept anyway since it's still the same one cheap lookup. `mtime` is a
// change-detection signal, not a required key: `cached.mtime === mtime`
// already matches when both are `null` (a server whose listing never
// yields a parseable mtime — see parseHtmlDirectoryListing), which is the
// right call — there's no evidence the file changed, as opposed to a
// mismatch, which is evidence that it did. Treating "unknown" as "assume
// changed" would defeat the cache on every single crawl instead of just
// when a file actually needs re-hydrating.
function resolveStub(author, fileName, mtime, authorRoot, cacheSnapshot) {
const path = `${authorRoot}${encodeURIComponent(fileName)}`;
const cached = cacheSnapshot.get(path);
if (cached && mtime != null && cached.mtime === mtime && cached.article?.hydrated) return cached.article;
if (cached && cached.mtime === mtime && cached.article?.hydrated) return cached.article;
return buildStub(author, fileName, mtime, authorRoot);
}