From 8d1d641f971776399182a427081757762579e920 Mon Sep 17 00:00:00 2001 From: Administrator Date: Sun, 21 Jun 2026 16:33:20 +0200 Subject: [PATCH] fix(update): cancel active uploads before downloading + add download stall-timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clicking 'install update' while many uploads were running left the update stuck at 'Update wird heruntergeladen...' forever, requiring a manual restart. Two causes, both fixed: 1) The 95 MB installer download competed with the active uploads for the (saturated) main process, CPU, network and connection pool, so it barely progressed. The install handler now calls uploadManager.cancel() first — the app quits and relaunches for the update anyway, and the queue is already persisted (non-terminal jobs restore as 'Bereit'), so freeing the resources is correct and makes the download fast. 2) The download read loop had no timeout, so a stalled stream hung indefinitely with no error. Added a 45 s stall-timeout: if no data arrives, the download aborts with a clear message ('Download haengt — seit 45 s keine Daten ... bitte erneut versuchen') instead of freezing, so the retry button works. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/updater.js | 19 ++++++++++++++++++- main.js | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/updater.js b/lib/updater.js index f935a4e..ac38810 100644 --- a/lib/updater.js +++ b/lib/updater.js @@ -179,10 +179,27 @@ async function installUpdate(onProgress) { let downloadedBytes = 0; const chunks = []; + const DOWNLOAD_STALL_MS = 45000; + let stallTimer = null; const reader = res.body.getReader(); while (true) { if (signal.aborted) throw new Error('Abgebrochen'); - const { done, value } = await reader.read(); + let chunk; + try { + chunk = await Promise.race([ + reader.read(), + new Promise((_, reject) => { stallTimer = setTimeout(() => reject(new Error('__STALL__')), DOWNLOAD_STALL_MS); }) + ]); + } catch (e) { + if (e && e.message === '__STALL__') { + try { activeAbort.abort(); } catch {} + throw new Error('Download hängt — seit 45 s keine Daten (Netzwerk/Server überlastet). Bitte laufende Uploads stoppen und erneut versuchen.'); + } + throw e; + } finally { + if (stallTimer) { clearTimeout(stallTimer); stallTimer = null; } + } + const { done, value } = chunk; if (done) break; chunks.push(value); downloadedBytes += value.length; diff --git a/main.js b/main.js index ea5308e..1add692 100644 --- a/main.js +++ b/main.js @@ -2294,6 +2294,7 @@ ipcMain.handle('app:check-updates', async () => { }); ipcMain.handle('app:install-update', () => { + try { if (uploadManager) uploadManager.cancel(); } catch {} installUpdate((progress) => { safeSend('app:update-progress', progress); }).catch((err) => {