diff --git a/main.js b/main.js index 4f7279d..867cfc9 100644 --- a/main.js +++ b/main.js @@ -32,10 +32,23 @@ const _sessionAccountOverrides = new Map(); // hoster -> account object // grepping account-rotation.log. Ring buffer per job keeps memory bounded. const _jobLogCollector = new Map(); // jobId -> Array const _MAX_LOG_ENTRIES_PER_JOB = 200; +// Cap the total number of jobs we keep history for — without this the Map +// keeps growing across batch-done boundaries (only start-upload clears it). +// 1000 jobs × 200 entries × ~100 bytes ≈ 20 MB worst case, bounded. +const _MAX_TRACKED_JOBS = 1000; function _appendJobLog(jobId, entry) { if (!jobId) return; let arr = _jobLogCollector.get(jobId); - if (!arr) { arr = []; _jobLogCollector.set(jobId, arr); } + if (!arr) { + arr = []; + _jobLogCollector.set(jobId, arr); + // Evict oldest tracked job (insertion order) once we're past the cap. + // Map iteration is insertion-ordered in spec, so .keys().next() is FIFO. + if (_jobLogCollector.size > _MAX_TRACKED_JOBS) { + const oldestId = _jobLogCollector.keys().next().value; + if (oldestId !== undefined) _jobLogCollector.delete(oldestId); + } + } if (arr.length >= _MAX_LOG_ENTRIES_PER_JOB) arr.shift(); arr.push(entry); } diff --git a/tasks/todo.md b/tasks/todo.md index cdce0e5..0a2e728 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -4,12 +4,10 @@ - ✅ 3.3.0 — Performance-Fixes (queue-cap, sort-throttle, history-delegation, recent-cap) + Log-Recovery - ✅ 3.3.1 — `removeFromQueueOnDone` coalesced via microtask (kein O(N²) mehr bei done-Bursts) - ✅ 3.3.2 — `fileuploader.log` Auto-Rotation bei 50 MB (max 3 Backups: .1 .2 .3) +- ✅ 3.3.3 — `_jobLogCollector` Cap auf 1000 tracked jobs (FIFO-eviction beim Überschreiten) ## Open items (priorisiert) -### Stabilität -- [ ] **`_jobLogCollector`** (main.js) — wird nur bei start-upload geleert, nicht bei batch-done. Bei vielen Batches ohne neuen start-upload wächst es. Cleanup bei batch-done für jobs die nicht mehr in queueJobs sind. - ### Performance - [ ] **`applyQueueSelectionClasses`** (renderer/app.js:891) — `tbody.querySelectorAll` bei jedem Klick. Bei 5000-Jobs-Queue O(N) per click. Cache last rendered range.