From 58a21ed321fc5f6a2ba6b9b944c1ee2e0a78c338 Mon Sep 17 00:00:00 2001 From: Administrator Date: Wed, 22 Apr 2026 18:56:24 +0200 Subject: [PATCH] fix(queue): stale sort-cache froze UI when queueJobs was replaced MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After importing a backup or restoring the queue at startup, queueJobs is reassigned to a fresh array. The sort-cache keyed its hit on "key|direction|length" — identical across a replacement with the same job count. Result: renderQueueTable kept getting the cached sorted array, which held references to the DISCARDED job objects (frozen at status='preview'). Uploads ran perfectly in the background, the status bar updated from stats events, but every row stayed "Bereit" with "..." as size. The user had to poke `_queueSortCache={sig:'',…}` in DevTools to unstick it. Include the jobs array identity (jobsRef) in the cache check. A replacement of queueJobs → different reference → cache miss → fresh sort with the real current objects. O(1) identity check, no CPU cost on the common case (same array, mutated jobs). --- renderer/app.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/renderer/app.js b/renderer/app.js index efa8e92..92e632e 100644 --- a/renderer/app.js +++ b/renderer/app.js @@ -1141,7 +1141,14 @@ const _collatorSimple = new Intl.Collator('de'); // Dynamic keys (status/speed/progress) AND size (which goes 0 → actual when // previews resolve / upload starts) are recomputed each call — otherwise a // queue sorted by size during previews would be stuck in all-zeros order. -let _queueSortCache = { sig: '', result: [] }; +// +// CRITICAL: the cache also tracks jobsRef (identity of the queueJobs array) so +// that a full replacement (e.g. backup import, queue restore) invalidates the +// cache. Length alone can match across a replace and would otherwise pin the +// renderer to stale job references — the UI freezes showing old statuses even +// though queueJobs itself has fresh objects. Observed as "upload runs in +// status bar but all rows stay 'Bereit'" after importing a backup. +let _queueSortCache = { sig: '', result: [], jobsRef: null }; const _STATIC_SORT_KEYS = new Set(['filename', 'host']); function sortQueueJobs(jobs) { @@ -1149,7 +1156,9 @@ function sortQueueJobs(jobs) { const factor = direction === 'asc' ? 1 : -1; const canCache = _STATIC_SORT_KEYS.has(key); const sig = canCache ? `${key}|${direction}|${jobs.length}` : ''; - if (sig && _queueSortCache.sig === sig) return _queueSortCache.result; + if (sig && _queueSortCache.sig === sig && _queueSortCache.jobsRef === jobs) { + return _queueSortCache.result; + } const sorted = jobs.slice().sort((a, b) => { let cmp = 0; @@ -1161,7 +1170,7 @@ function sortQueueJobs(jobs) { else if (key === 'progress') cmp = (a.progress || 0) - (b.progress || 0); return cmp * factor; }); - if (sig) _queueSortCache = { sig, result: sorted }; + if (sig) _queueSortCache = { sig, result: sorted, jobsRef: jobs }; return sorted; }