From 6cdfc9fc25d96a3f894286a9ad913ea87b1760ea Mon Sep 17 00:00:00 2001 From: Faur Ioan-Aurel Date: Mon, 14 Apr 2025 17:11:32 +0300 Subject: [PATCH] fix: simplify and improve error handling during workspace polling - detect if there is os wake-up for all types of errors - if there is an os wake-up we try to re-init the http client - if that doesn't work out, the polling stops and redirects to the autologin screen. - the autologin screen will display an error and stop the authentication if errors are encountered --- CHANGELOG.md | 4 +++ .../com/coder/toolbox/CoderRemoteProvider.kt | 30 ++++--------------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c3ec3f..4aeefed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - login screen is shown instead of an empty list of workspaces when token expired +### Changed + +- improved error handling during workspace polling + ## 0.1.4 - 2025-04-11 ### Fixed diff --git a/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt b/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt index 292e276..186b023 100644 --- a/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt +++ b/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt @@ -2,7 +2,6 @@ package com.coder.toolbox import com.coder.toolbox.cli.CoderCLIManager import com.coder.toolbox.sdk.CoderRestClient -import com.coder.toolbox.sdk.ex.APIResponseException import com.coder.toolbox.sdk.v2.models.WorkspaceStatus import com.coder.toolbox.util.CoderProtocolHandler import com.coder.toolbox.util.DialogUi @@ -30,7 +29,6 @@ import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.selects.onTimeout import kotlinx.coroutines.selects.select -import java.net.SocketTimeoutException import java.net.URI import kotlin.coroutines.cancellation.CancellationException import kotlin.time.Duration.Companion.seconds @@ -58,11 +56,6 @@ class CoderRemoteProvider( // The REST client, if we are signed in private var client: CoderRestClient? = null - // If we have an error in the polling we store it here before going back to - // sign-in page, so we can display it there. This is mainly because there - // does not seem to be a mechanism to show errors on the environment list. - private var errorBuffer = mutableListOf() - // On the first load, automatically log in if we can. private var firstRun = true private val isInitialized: MutableStateFlow = MutableStateFlow(false) @@ -135,29 +128,17 @@ class CoderRemoteProvider( } catch (_: CancellationException) { context.logger.debug("${client.url} polling loop canceled") break - } catch (ex: SocketTimeoutException) { + } catch (ex: Exception) { val elapsed = lastPollTime.elapsedNow() if (elapsed > POLL_INTERVAL * 2) { context.logger.info("wake-up from an OS sleep was detected, going to re-initialize the http client...") client.setupSession() } else { - context.logger.error(ex, "workspace polling error encountered") - errorBuffer.add(ex) - logout() + context.logger.error(ex, "workspace polling error encountered, trying to auto-login") + close() + goToEnvironmentsPage() break } - } catch (ex: APIResponseException) { - context.logger.error(ex, "error in contacting ${client.url} while polling the available workspaces") - errorBuffer.add(ex) - logout() - goToEnvironmentsPage() - break - } catch (ex: Exception) { - context.logger.error(ex, "workspace polling error encountered") - errorBuffer.add(ex) - logout() - goToEnvironmentsPage() - break } // TODO: Listening on a web socket might be better? @@ -306,6 +287,7 @@ class CoderRemoteProvider( override fun getOverrideUiPage(): UiPage? { // Show sign in page if we have not configured the client yet. if (client == null) { + val errorBuffer = mutableListOf() // When coming back to the application, authenticate immediately. val autologin = shouldDoAutoLogin() context.secrets.lastToken.let { lastToken -> @@ -329,7 +311,6 @@ class CoderRemoteProvider( authWizard.notify("Error encountered", it) } // and now reset the errors, otherwise we show it every time on the screen - errorBuffer.clear() return authWizard } return null @@ -344,7 +325,6 @@ class CoderRemoteProvider( // Currently we always remember, but this could be made an option. context.secrets.rememberMe = true this.client = client - errorBuffer.clear() pollJob?.cancel() pollJob = poll(client, cli) goToEnvironmentsPage()