@@ -3,6 +3,7 @@ package com.coder.toolbox
33import com.coder.toolbox.browser.browse
44import com.coder.toolbox.cli.CoderCLIManager
55import com.coder.toolbox.sdk.CoderRestClient
6+ import com.coder.toolbox.sdk.ex.APIResponseException
67import com.coder.toolbox.sdk.v2.models.WorkspaceStatus
78import com.coder.toolbox.util.CoderProtocolHandler
89import com.coder.toolbox.util.DialogUi
@@ -20,7 +21,6 @@ import com.jetbrains.toolbox.api.core.util.LoadableState
2021import com.jetbrains.toolbox.api.localization.LocalizableString
2122import com.jetbrains.toolbox.api.remoteDev.ProviderVisibilityState
2223import com.jetbrains.toolbox.api.remoteDev.RemoteProvider
23- import com.jetbrains.toolbox.api.remoteDev.RemoteProviderEnvironment
2424import com.jetbrains.toolbox.api.ui.actions.ActionDelimiter
2525import com.jetbrains.toolbox.api.ui.actions.ActionDescription
2626import com.jetbrains.toolbox.api.ui.components.UiPage
@@ -66,7 +66,8 @@ class CoderRemoteProvider(
6666 private val isInitialized: MutableStateFlow <Boolean > = MutableStateFlow (false )
6767 private var coderHeaderPage = NewEnvironmentPage (context, context.i18n.pnotr(context.deploymentUrl.toString()))
6868 private val linkHandler = CoderProtocolHandler (context, dialogUi, isInitialized)
69- override val environments: MutableStateFlow <LoadableState <List <RemoteProviderEnvironment >>> = MutableStateFlow (
69+
70+ override val environments: MutableStateFlow <LoadableState <List <CoderRemoteEnvironment >>> = MutableStateFlow (
7071 LoadableState .Loading
7172 )
7273
@@ -127,7 +128,7 @@ class CoderRemoteProvider(
127128 environments.update {
128129 LoadableState .Value (resolvedEnvironments.toList())
129130 }
130- if (isInitialized.value == false ) {
131+ if (! isInitialized.value) {
131132 context.logger.info(" Environments for ${client.url} are now initialized" )
132133 isInitialized.update {
133134 true
@@ -137,6 +138,21 @@ class CoderRemoteProvider(
137138 clear()
138139 addAll(resolvedEnvironments.sortedBy { it.id })
139140 }
141+
142+ if (WorkspaceConnectionManager .shouldEstablishWorkspaceConnections) {
143+ WorkspaceConnectionManager .allConnected().forEach { wsId ->
144+ val env = lastEnvironments.firstOrNull() { it.id == wsId }
145+ if (env != null && ! env.isConnected()) {
146+ context.logger.info(" Establishing lost SSH connection for workspace with id $wsId " )
147+ if (! env.startSshConnection()) {
148+ context.logger.info(" Can't establish lost SSH connection for workspace with id $wsId " )
149+ }
150+ }
151+ }
152+ WorkspaceConnectionManager .reset()
153+ }
154+
155+ WorkspaceConnectionManager .collectStatuses(lastEnvironments)
140156 } catch (_: CancellationException ) {
141157 context.logger.debug(" ${client.url} polling loop canceled" )
142158 break
@@ -147,6 +163,9 @@ class CoderRemoteProvider(
147163 client.setupSession()
148164 } else {
149165 context.logger.error(ex, " workspace polling error encountered, trying to auto-login" )
166+ if (ex is APIResponseException && ex.isTokenExpired) {
167+ WorkspaceConnectionManager .shouldEstablishWorkspaceConnections = true
168+ }
150169 close()
151170 // force auto-login
152171 firstRun = true
@@ -179,6 +198,7 @@ class CoderRemoteProvider(
179198 // Keep the URL and token to make it easy to log back in, but set
180199 // rememberMe to false so we do not try to automatically log in.
181200 context.secrets.rememberMe = false
201+ WorkspaceConnectionManager .reset()
182202 close()
183203 }
184204
@@ -361,7 +381,7 @@ class CoderRemoteProvider(
361381 goToEnvironmentsPage()
362382 }
363383
364- private fun MutableStateFlow<LoadableState<List<RemoteProviderEnvironment >>>.showLoadingMessage () {
384+ private fun MutableStateFlow<LoadableState<List<CoderRemoteEnvironment >>>.showLoadingMessage () {
365385 this .update {
366386 LoadableState .Loading
367387 }
0 commit comments