fix: add translator queue limit, periodic cleanup, and node checks

This commit is contained in:
2026-04-15 07:27:01 -07:00
parent fba25a9081
commit 6582ddf93a
+43 -2
View File
@@ -104,7 +104,7 @@ const FALSE_POSITIVE_LANGS = new Set([
// ── Auto-suppression (repeated short phrases) ──
const suppressionCounts = new Map<string, number>();
let suppressionCounts = new Map<string, number>();
const SUPPRESS_THRESHOLD = 3;
const MIN_LATIN_WORDS = 3;
const SHORT_TEXT_THRESHOLD = 15;
@@ -113,6 +113,7 @@ const SHORT_TEXT_THRESHOLD = 15;
let activeRequests = 0;
const MAX_CONCURRENT = 3;
const MAX_QUEUE = 15;
const pendingQueue: Array<() => void> = [];
function enqueue(fn: () => Promise<void>): void {
@@ -123,10 +124,45 @@ function enqueue(fn: () => Promise<void>): void {
if (pendingQueue.length > 0) pendingQueue.shift()!();
});
} else {
// Drop oldest if queue is full — old messages have already scrolled off-screen
if (pendingQueue.length >= MAX_QUEUE) pendingQueue.shift();
pendingQueue.push(() => enqueue(fn));
}
}
// ── Periodic cleanup (prevents unbounded memory growth in long sessions) ──
const CLEANUP_INTERVAL_MS = 5 * 60 * 1000;
let cleanupTimer: ReturnType<typeof setInterval> | null = null;
function startCleanup(): void {
if (cleanupTimer) return;
cleanupTimer = setInterval(() => {
// Reset suppression counts (re-learned naturally from fresh messages)
suppressionCounts = new Map();
// Prune expired sessionStorage cache entries
const now = Date.now();
const keysToRemove: string[] = [];
for (let i = 0; i < sessionStorage.length; i++) {
const key = sessionStorage.key(i);
if (!key?.startsWith(CACHE_KEY_PREFIX)) continue;
try {
const entry: CacheEntry = JSON.parse(sessionStorage.getItem(key) || '');
if (now - entry.ts > CACHE_EXPIRY_MS) keysToRemove.push(key);
} catch { keysToRemove.push(key); }
}
for (const key of keysToRemove) sessionStorage.removeItem(key);
}, CLEANUP_INTERVAL_MS);
}
function stopCleanup(): void {
if (cleanupTimer) {
clearInterval(cleanupTimer);
cleanupTimer = null;
}
}
// ── System message patterns to skip ──
const SYSTEM_PATTERNS = [
@@ -281,8 +317,10 @@ function processMessage(node: HTMLElement): void {
const { message, username } = extracted;
enqueue(async () => {
// Node may have been removed by chat history trimming while queued
if (!node.isConnected) return;
const result = await translateText(message);
if (result) appendTranslation(node, username, result.translation, result.srcLang);
if (result && node.isConnected) appendTranslation(node, username, result.translation, result.srcLang);
});
}
@@ -316,6 +354,7 @@ function startObserver(): void {
});
chatObserver.observe(chatList, { childList: true });
startCleanup();
_con.log('[KCC-TL] Chat observer active');
}, 500);
}
@@ -329,6 +368,8 @@ function stopObserver(): void {
chatObserver.disconnect();
chatObserver = null;
}
stopCleanup();
pendingQueue.length = 0;
}
// ── Public API ──