fix(watch-history): stop infinite feed-refresh loop pegging the CPU

updateFingerprintCache (and the fingerprint getter) emitted "fingerprint"
unconditionally on every load. The For You feed subscribes to that event and
re-runs refreshFeed -> loadLatest -> updateFingerprintCache -> emit, so once the
For You feed was active the app entered an infinite loop: a full feed rebuild
plus a watch-history reload (with extension decrypts) every ~400ms. That pegged
the CPU (fans maxing) and starved every other load — videos, hashtags, subs,
DMs and watch history all failed to appear.

Emit "fingerprint" only when the fingerprint actually changes. The first real
resolution emits once (triggering a single refresh); the follow-up load produces
the same fingerprint and emits nothing, so the loop settles immediately.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-06-13 07:57:04 -04:00
1 parent 9dddda0326
commit 915b77b740
1 file changed
+16 -2
+16 -2
View File
@@ -663,6 +663,7 @@ async function updateFingerprintCache(actorKey, items) {
items
);
const entry = state.fingerprintCache.get(actorKey) || {};
const previousFingerprint = entry.fingerprint;
const nextEntry = {
...entry,
items: Array.isArray(items) ? items : [],
@@ -671,7 +672,17 @@ async function updateFingerprintCache(actorKey, items) {
};
delete nextEntry.promise;
state.fingerprintCache.set(actorKey, nextEntry);
emit("fingerprint", { actor: actorKey, fingerprint, items: nextEntry.items });
// Only emit when the fingerprint actually CHANGED. Emitting unconditionally
// created an infinite loop: the For You feed listens for "fingerprint" and
// re-runs refreshFeed -> loadLatest -> updateFingerprintCache -> emit, which
// pegged the CPU with a full feed rebuild every ~400ms.
if (fingerprint !== previousFingerprint) {
emit("fingerprint", {
actor: actorKey,
fingerprint,
items: nextEntry.items,
});
}
return fingerprint;
}
@@ -1337,13 +1348,16 @@ async function getFingerprint(actorInput) {
}
const fingerprint = await nostrClient.getWatchHistoryFingerprint(actorKey);
const ttl = Math.max(0, Number(WATCH_HISTORY_CACHE_TTL_MS) || 0);
const previousFingerprint = cacheEntry?.fingerprint;
const nextEntry = {
...(cacheEntry || {}),
fingerprint,
expiresAt: now + ttl,
};
state.fingerprintCache.set(actorKey, nextEntry);
emit("fingerprint", { actor: actorKey, fingerprint });
if (fingerprint !== previousFingerprint) {
emit("fingerprint", { actor: actorKey, fingerprint });
}
return fingerprint;
}