Bundles four findings from a stability audit plus the missing-log bug the user reported. 1. main.js _flushUploadLog: ENOENT after the log file's directory got deleted mid-session was swallowed; the buffer was cleared before appendFile so entries were silently lost and the cached target kept pointing at the dead path. Now: mkdirSync(recursive) before every flush idempotently recreates a missing dir; on any append error we invalidate the cache, prepend the chunk back to the buffer and schedule a retry. Survives "user dragged the log folder into the trash and didn't notice". 2. renderer/app.js queueJobs auto-prune: with the default removeFromQueueOnDone=false the queue grew forever. Past ~5000 entries every render became O(N) on a perpetually-growing N and the user saw progressive scroll/tab lag. Cap the in-queue terminal jobs (done/skipped/error/aborted) at 500 most-recent on each batch-done; oldest get pruned with their index entries. 3. sortQueueJobs dynamic-key throttle: status/speed/progress/size sorts ran a full O(N log N) sort on every progress tick. Added a 200ms-window cache for the dynamic-key path so the sort is reused within the same UI_UPDATE_INTERVAL — invisibly small reorder lag, massive cost savings at 5000+ jobs. 4. renderHistoryTable delegated listeners: every Verlauf-tab switch was binding one click listener per row (5000 listeners on a long-history user) and rebuilding the entire <tbody> innerHTML. Single delegated tbody listener covers both row-click (copy link) and th-click (sort), bound once per container via dataset flag. 5. sessionFilesData (recent-files panel) cap at 2000 entries with matching _sessionFileKeys cleanup using the existing separator. Stops the lower-panel innerHTML write from inflating to multiple MB on long sessions. 87/87 tests still green.
33 lines
2.0 KiB
Markdown
33 lines
2.0 KiB
Markdown
# 3.3.0 — Performance + Log-Recovery
|
||
|
||
## Probleme (User-Bericht)
|
||
1. Lag beim Tab-Wechsel + Scrollen nach langer Session.
|
||
2. File-Uploader-Log: bei einem von zwei Hostern gar keine Log-Einträge — möglicherweise nach Datei/Verzeichnis-Löschung kein Recovery.
|
||
|
||
## Root Causes (aus Audit)
|
||
|
||
### Performance
|
||
- **queueJobs wächst unbounded** (Default `removeFromQueueOnDone=false`). Sortierung + Stats + In-place-Render skalieren O(N) und O(N log N) je render. Nach ~5000 Jobs spürbar.
|
||
- **`sortQueueJobs` cached nur für static keys** (filename, host). Bei status/speed/progress: voller Sort jedes Mal.
|
||
- **`renderHistoryTable`** bindet per-row click listener + voller `innerHTML`-Rebuild bei jedem Tab-Switch.
|
||
- **`renderRecentUploadsPanel`** baut komplettes innerHTML bei sort-change neu, `sessionFilesData` Array ungecapt.
|
||
|
||
### Log-Bug
|
||
- `_flushUploadLog` clear buffer **vor** appendFile. Bei `ENOENT` (Datei oder Dir wurde gelöscht) → silent log + buffer verloren.
|
||
- `_resolveUploadLogTarget` cached den Path. Bei mid-session Verzeichnis-Löschung wird der cached target wiederverwendet → permanent ENOENT bis Neustart.
|
||
|
||
## Plan
|
||
- [ ] Log: bei error in `appendFile` → cache invalidieren + buffer prepend + retry
|
||
- [ ] Log: vor jedem flush mkdirSync (idempotent, recreated deleted dir)
|
||
- [ ] queueJobs: auto-prune nach `handleBatchDone` für älteste 'done' jobs jenseits Cap (z.B. 500)
|
||
- [ ] sortQueueJobs: für dynamic keys → coalesce auf 1× pro UI_UPDATE_INTERVAL (200ms)
|
||
- [ ] renderHistoryTable: delegated click-listener auf tbody (nicht per-row), short-circuit wenn `_historyDirty=false`
|
||
- [ ] renderRecentUploadsPanel: `sessionFilesData` auf letzten 2000 Einträge cappen, `_sessionFileKeys` parallel prunen
|
||
- [ ] removeFromQueueOnDone: O(N²) → splice via `_jobIndexById` (oder defer auf batch-done)
|
||
- [ ] Tests: Log-recovery, queue-prune, sort-throttle
|
||
- [ ] Release als 3.3.0
|
||
|
||
## Skip (Low Impact / kosmetisch)
|
||
- CSS transition fix
|
||
- Module-level Sets clearing (genug Memory bisher)
|