From 1f693be9fcbf5201a26600c308f660a80a3df03d Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:40:42 -0800 Subject: [PATCH] Auto-retry transient update errors once --- ts/updater/common.ts | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/ts/updater/common.ts b/ts/updater/common.ts index aa3f3e9a84..08a0a6ee99 100644 --- a/ts/updater/common.ts +++ b/ts/updater/common.ts @@ -111,6 +111,10 @@ enum CheckType { ForceDownload = 'ForceDownload', } +const MAX_AUTO_RETRY_ATTEMPTS = 1; + +const AUTO_RETRY_DELAY = durations.DAY; + export abstract class Updater { protected fileName: string | undefined; @@ -139,6 +143,10 @@ export abstract class Updater { private readonly canRunSilently: () => boolean; + private autoRetryAttempts = 0; + + private autoRetryAfter: number | undefined; + constructor({ settingsChannel, logger, @@ -268,7 +276,7 @@ export abstract class Updater { ); const timeoutMs = selectedPollTime - now; - this.logger.info(`updater/start: polling in ${timeoutMs}ms`); + this.logger.info(`updater/schedulePoll: polling in ${timeoutMs}ms`); setTimeout(() => { drop(this.safePoll()); @@ -277,10 +285,17 @@ export abstract class Updater { private async safePoll(): Promise { try { - this.logger.info('updater/start: polling now'); + if (this.autoRetryAfter != null && Date.now() < this.autoRetryAfter) { + this.logger.info( + `updater/safePoll: not polling until ${this.autoRetryAfter}` + ); + return; + } + + this.logger.info('updater/safePoll: polling now'); await this.checkForUpdatesMaybeInstall(CheckType.Normal); } catch (error) { - this.logger.error(`updater/start: ${Errors.toLogFormat(error)}`); + this.logger.error(`updater/safePoll: ${Errors.toLogFormat(error)}`); } finally { this.schedulePoll(); } @@ -323,9 +338,27 @@ export abstract class Updater { // Restore state in case of download error this.version = oldVersion; + if ( + mode === DownloadMode.Automatic && + this.autoRetryAttempts < MAX_AUTO_RETRY_ATTEMPTS + ) { + this.autoRetryAttempts += 1; + this.autoRetryAfter = Date.now() + AUTO_RETRY_DELAY; + logger.warn( + 'downloadAndInstall: transient error ' + + `${Errors.toLogFormat(error)}, ` + + `attempts=${this.autoRetryAttempts}, ` + + `retryAfter=${this.autoRetryAfter}` + ); + return false; + } + throw error; } + this.autoRetryAttempts = 0; + this.autoRetryAfter = undefined; + if (!downloadResult) { logger.warn('downloadAndInstall: no update was downloaded'); strictAssert( @@ -389,7 +422,9 @@ export abstract class Updater { return true; } catch (error) { - logger.error(`downloadAndInstall: ${Errors.toLogFormat(error)}`); + logger.error( + `downloadAndInstall: fatal error ${Errors.toLogFormat(error)}` + ); this.markCannotUpdate(error); throw error; }