authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-03-03 21:14:40-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-03-03 22:31:45-08:00
log3cffdce1c157bce72fda86a62376810e7c399b71
tree8edf18e6c7e68116090efe5d66c72a8fcf3ead57
parent6d2f4f4cdf257cf84e7b89aae14c0d9781392216

Harden desktop auto-update timer lifecycle

- track and clear startup + poll update timers through one cleanup path - prevent update checks from starting while the app is quitting - reset startup timer before scheduling to avoid duplicate checks

1 files changed, 15 insertions(+), 6 deletions(-)

apps/desktop/src/main.ts+15-6
...@@ -203,6 +203,7 @@ function getDestructiveMenuIcon(): Electron.NativeImage | undefined {...@@ -203,6 +203,7 @@ function getDestructiveMenuIcon(): Electron.NativeImage | undefined {
203 }203 }
204}204}
205let updatePollTimer: ReturnType<typeof setInterval> | null = null;205let updatePollTimer: ReturnType<typeof setInterval> | null = null;
206let updateStartupTimer: ReturnType<typeof setTimeout> | null = null;
206let updateCheckInFlight = false;207let updateCheckInFlight = false;
207let updateDownloadInFlight = false;208let updateDownloadInFlight = false;
208let updaterConfigured = false;209let updaterConfigured = false;
...@@ -538,9 +539,14 @@ function configureAppIdentity(): void {...@@ -538,9 +539,14 @@ function configureAppIdentity(): void {
538}539}
539540
540function clearUpdatePollTimer(): void {541function clearUpdatePollTimer(): void {
541 if (!updatePollTimer) return;542 if (updateStartupTimer) {
542 clearInterval(updatePollTimer);543 clearTimeout(updateStartupTimer);
543 updatePollTimer = null;544 updateStartupTimer = null;
545 }
546 if (updatePollTimer) {
547 clearInterval(updatePollTimer);
548 updatePollTimer = null;
549 }
544}550}
545551
546function emitUpdateState(): void {552function emitUpdateState(): void {
...@@ -570,7 +576,7 @@ function shouldEnableAutoUpdates(): boolean {...@@ -570,7 +576,7 @@ function shouldEnableAutoUpdates(): boolean {
570}576}
571577
572async function checkForUpdates(reason: string): Promise<void> {578async function checkForUpdates(reason: string): Promise<void> {
573 if (!updaterConfigured || updateCheckInFlight) return;579 if (isQuitting || !updaterConfigured || updateCheckInFlight) return;
574 if (580 if (
575 updateState.status === "downloading" ||581 updateState.status === "downloading" ||
576 updateState.status === "downloaded" ||582 updateState.status === "downloaded" ||
...@@ -739,10 +745,13 @@ function configureAutoUpdater(): void {...@@ -739,10 +745,13 @@ function configureAutoUpdater(): void {
739 console.info(`[desktop-updater] Update downloaded: ${info.version}`);745 console.info(`[desktop-updater] Update downloaded: ${info.version}`);
740 });746 });
741747
742 const startupTimer = setTimeout(() => {748 clearUpdatePollTimer();
749
750 updateStartupTimer = setTimeout(() => {
751 updateStartupTimer = null;
743 void checkForUpdates("startup");752 void checkForUpdates("startup");
744 }, AUTO_UPDATE_STARTUP_DELAY_MS);753 }, AUTO_UPDATE_STARTUP_DELAY_MS);
745 startupTimer.unref();754 updateStartupTimer.unref();
746755
747 updatePollTimer = setInterval(() => {756 updatePollTimer = setInterval(() => {
748 void checkForUpdates("poll");757 void checkForUpdates("poll");