Open Brainshaker95 opened 1 year ago
This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days.
Can someone please provide some additional insights? Any help would be greatly appreciated.
@Brainshaker95 sorry, just now seeing this in my feed. How are you canceling the update? I can try investigating it locally if you're willing to provide a minimum reproducible repo?
@mmaietta Sorry I only just noticed that I got an answer here...
This is the repo I used: https://github.com/Brainshaker95/update-test
There is also some other unnecessary junk in there since it originally came from a much larger project but the general repro is the same as documented here.
The project can be setup using yarn
and yarn build:all
. I am also happy to provide a new repository with only the bare minimum code to show the issue, but I would need some time for that. Let me know if this already suffices.
How are you canceling the update?
Using the cancel
method on the cancellationToken passed to autoUpdater.downloadUpdate
This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days.
I noticed that the autoUpdater does not fire the
download-progress
event when retrying the download multiple times. I have broken down the issue already but I am not sure what the exact cause of this behavior is. I will try to explain with the following reduced example:Note that in my real application the triggers are user controlled, this is just for demonstration
package.json
```json { "name": "update-test", "version": "0.0.1", "description": "This is a test", "main": "main.cjs", "scripts": { "build": "electron-builder -w --x64 --config ./electron.config.cjs" }, "dependencies": { "builder-util-runtime": "9.2.1", "electron-log": "4.4.8", "electron-updater": "6.1.4" }, "devDependencies": { "electron": "26.2.2", "electron-builder": "24.6.4" }, "repository": { "type": "git", "url": "git+https://github.com/electron.config.cjs
```js /** * @type {import('electron-builder').Configuration} */ module.exports = { appId: 'com.main.cjs
```js const path = require('path'); const { CancellationError } = require('builder-util-runtime'); const { app, BrowserWindow, ipcMain } = require('electron'); const log = require('electron-log'); const { autoUpdater, CancellationToken } = require('electron-updater'); log.transports.file.level = 'info'; autoUpdater.logger = log; autoUpdater.autoDownload = false; autoUpdater.disableWebInstaller = true; /** * @type {import('electron').BrowserWindow | null} */ let mainWindow = null; /** * @type {import('electron-updater').CancellationToken | null} */ let cancellationToken = null; const createMainWindow = () => { mainWindow = new BrowserWindow({ title: 'Update Test', show: false, webPreferences: { nodeIntegration: true, preload: path.join(__dirname, 'preload.cjs'), }, }); mainWindow .once('ready-to-show', () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); } }) .on('close', () => { mainWindow = null; }); mainWindow.loadFile('index.html'); }; autoUpdater.on('checking-for-update', () => { mainWindow?.webContents.send('update-checking'); }); autoUpdater.on('update-available', (info) => { mainWindow?.webContents.send('update-available', info); }); autoUpdater.on('error', (error) => { log.error('error during update:', error); }); autoUpdater.on('update-cancelled', () => { mainWindow?.webContents.send('update-cancelled'); }); autoUpdater.on('download-progress', (progress) => { mainWindow?.webContents.send('download-progress', progress); log.info('download progress:', progress.percent); }); ipcMain.on('download-update', () => { cancellationToken = new CancellationToken(); autoUpdater .downloadUpdate(cancellationToken) .catch((error) => { if (error instanceof CancellationError) { return; } log.error('error during downloadUpdate:', error); }); }); ipcMain.on('cancel-update', () => { cancellationToken?.cancel(); }); ipcMain.on('check-for-update', () => { autoUpdater .checkForUpdates() .then((result) => { if (result?.cancellationToken) { ({ cancellationToken } = result); } }) .catch((error) => { if (error instanceof CancellationError) { return; } log.info('error during checkForUpdates', error); }); }); app .once('ready', createMainWindow) .on('window-all-closed', () => { app.quit(); }); ```preload.cjs
```js const { ipcRenderer } = require('electron'); const delay = (ms = 1000) => new Promise((resolve) => { setTimeout(resolve, ms); }); delay(5000).then(() => ipcRenderer.send('check-for-update')); ipcRenderer.on('update-available', () => { ipcRenderer.send('download-update'); }); ipcRenderer.on('download-progress', () => { delay().then(() => ipcRenderer.send('cancel-update')); }); ipcRenderer.on('update-cancelled', () => { delay().then(() => ipcRenderer.send('download-update')); }); ```main.log
```log [2023-09-26 21:58:30.273] [info] Checking for update [2023-09-26 21:58:31.185] [info] Found version 0.0.2 (url: Update-Test-Setup-0.0.2.exe) [2023-09-26 21:58:31.187] [info] Downloading update from Update-Test-Setup-0.0.2.exe [2023-09-26 21:58:31.190] [info] Download block maps (old: "https://github.com/So basically it goes like this:
-> check for update
-> start download
-> download progress
-> cancel download
-> start download
-> download progress
-> cancel download
-> start download
=> process hangs and no
download-progress
event is emittedI tracked it down to the electron-updater HttpExecutor ProgressCallbackTransform stream which seemingly stops sending progress updates after a while.
I tried adding the following log statement in this loop to visualize when exactly it stops:
I noticed that this stream does not receive any more data after retrying about 2 times (it's not always consistent for me), but it also doesn't throw an error or close. Is this some kind of intended behavior or have I ran into an edge case? Any help would be greatly appreciated. Let me know if I can help with any additional information.