Commit Graph

6 Commits

Author SHA1 Message Date
Administrator
66f8b47b6d perf+fix: long-session lag, tab-switch lag, log-recovery
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.
2026-04-28 03:30:33 +02:00
Administrator
d49fe136f2 fix+obs: byse poller race-condition + transient-net tests + memory logging
Three small, unrelated reliability improvements bundled:

1. lib/hosters.js (_resolveByseUploadByName): drop the "only one new
   file → claim it" fallback. Under parallel byse uploads, job A's
   poller could claim job B's newly-uploaded file and return the wrong
   URL. Now requires exact normalized name match. Trade-off: a few
   false negatives if byse rewrites the filename beyond our
   normalizer, but parallel correctness wins.

2. tests/upload-manager.test.js: pin the transient-network classifier
   behaviour with 2 new tests covering common transient strings
   (ENOTFOUND, ECONNRESET, socket hang up, fetch failed, EAI_AGAIN…)
   and verifying real account-level / file-rejected errors are NOT
   misclassified as transient. Baseline stays clean: 82/82 green.

3. main.js: log process.memoryUsage() snapshot at batch-start and
   batch-done. One line each — harmless in the happy path, gives us
   the data points needed to spot long-session RSS/heap growth across
   batches without DevTools instrumentation.
2026-04-21 19:42:54 +02:00
Administrator
a6ff2dd587 chore(main): drop JSON.stringify of files/hosters in start-upload log
At 500+ queued jobs these lines bloated upload-debug.log with
megabyte-sized entries per batch-start and added visible latency to
the IPC handler. Log sizes only.
2026-04-21 19:31:07 +02:00
Administrator
bf806cb069 fix(rotation): session-learning for account failures is now complete
Three related gaps closed so one full byse account stops wasting
attempts on every subsequent job and later-added accounts get picked
up without an app restart.

1. Pre-job-swap moved BEHIND the semaphore acquire. At scale (500 jobs
   / 1 slot) every worker was checking _failedAccounts at spawn time
   before the first upload had even tried — so none of them saw the
   failed state. Now each worker re-checks right before its first
   upload attempt.

2. save-config IPC handler re-resolves fallbacks for any account that
   is already in _failedAccounts but has no override set. Previously
   account-failed only fired once per account, so a config change
   after the first mark-failed was silently ignored and the batch
   stayed stuck on the dead account until the app restarted.

3. UploadManager exposes getFailedAccountKeys() and getOverride(hoster)
   so main.js can drive the late re-resolve without poking private
   fields.

4 new tests: pre-job-swap after semaphore, getters contract, fresh
manager resets learned state, late-added fallback is honored by
subsequent jobs. 80/80 green.
2026-04-21 17:03:59 +02:00
Administrator
17e9a419b2 fix(rotation): treat byse "disk space" as account-level, not file-rejected
Byse rejects uploads with status like "not enough disk space on your
account" when the account's storage is exhausted. The parser was
flagging every non-OK status as err.fileRejected=true, and the upload-
manager classifier additionally matched the generic "lehnte Datei ab"
prefix as file-rejected. Result: rotation was skipped on a full account
and every subsequent file failed on the same dead account.

- hosters.js: byse parser now distinguishes account-level phrases
  (disk space / storage / quota / insufficient / account full) and sets
  err.accountError=true for those. File-specific failures (Duplicate,
  wrong format, size) keep err.fileRejected=true.
- upload-manager.js: _isFileRejectedError no longer matches the generic
  "lehnte Datei ab" prefix and short-circuits when err.accountError is
  true. _shouldSkipRetryOnAccountError honors the flag and has added
  regex patterns as a safety net.
- Tests: 5 new unit tests covering disk-space/account-level/duplicate
  and the accountError-wins-over-fileRejected precedence.
2026-04-21 16:42:56 +02:00
Administrator
f3b1c25d8b perf(queue): halve sync work on retry of many jobs
retrySelectedJobs() was calling renderQueueTable + updateQueueActionButtons
+ updateStatusBar and then immediately awaiting startSelectedUpload(),
which runs the exact same trio right after. At 500+ failed jobs the
double render/sort/button-refresh freezes the UI for several seconds
after clicking "Erneut versuchen".

Drop the outer render trio — startSelectedUpload's one is enough. The
inner call sees the freshly-mutated job state in the same tick, so the
visible result is identical with half the work.
2026-04-21 16:14:58 +02:00