Skip to content

Commit 244dde9

Browse files
committed
Catch&report errors raised by the REST client
- the exceptions from the rest client were handled by the coroutine scope which canceled everything in the scope without any event logged to the user. - the exceptions are now catched inside the coroutine scope & logged. - any error logged through the diagnostic logger is also displayed in the Gateway UI through the internal errors message panel (red balloon in the bottom right corner)
1 parent 5ca0790 commit 244dde9

File tree

6 files changed

+50
-24
lines changed

6 files changed

+50
-24
lines changed

src/main/kotlin/com/coder/gateway/sdk/CoderRestClientService.kt

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package com.coder.gateway.sdk
22

33
import com.coder.gateway.sdk.convertors.InstantConverter
4-
import com.coder.gateway.sdk.ex.AuthenticationException
4+
import com.coder.gateway.sdk.ex.AuthenticationResponseException
5+
import com.coder.gateway.sdk.ex.WorkspaceResponseException
56
import com.coder.gateway.sdk.v2.CoderV2RestFacade
67
import com.coder.gateway.sdk.v2.models.BuildInfo
78
import com.coder.gateway.sdk.v2.models.User
@@ -30,7 +31,7 @@ class CoderRestClientService {
3031

3132
/**
3233
* This must be called before anything else. It will authenticate with coder and retrieve a session token
33-
* @throws [AuthenticationException] if authentication failed
34+
* @throws [AuthenticationResponseException] if authentication failed.
3435
*/
3536
fun initClientSession(url: URL, token: String): User {
3637
val cookieUrl = url.toHttpUrlOrNull()!!
@@ -61,7 +62,7 @@ class CoderRestClientService {
6162

6263
val userResponse = retroRestClient.me().execute()
6364
if (!userResponse.isSuccessful) {
64-
throw IllegalStateException("Could not retrieve information about logged use:${userResponse.code()}, reason: ${userResponse.message()}")
65+
throw AuthenticationResponseException("Could not retrieve information about logged user:${userResponse.code()}, reason: ${userResponse.message()}")
6566
}
6667

6768
coderURL = url
@@ -72,10 +73,14 @@ class CoderRestClientService {
7273
return me
7374
}
7475

76+
/**
77+
* Retrieves the available workspaces created by the user.
78+
* @throws WorkspaceResponseException if workspaces could not be retrieved.
79+
*/
7580
fun workspaces(): List<Workspace> {
7681
val workspacesResponse = retroRestClient.workspaces().execute()
7782
if (!workspacesResponse.isSuccessful) {
78-
throw IllegalStateException("Could not retrieve Coder Workspaces:${workspacesResponse.code()}, reason: ${workspacesResponse.message()}")
83+
throw WorkspaceResponseException("Could not retrieve Coder Workspaces:${workspacesResponse.code()}, reason: ${workspacesResponse.message()}")
7984
}
8085

8186
return workspacesResponse.body()!!

src/main/kotlin/com/coder/gateway/sdk/ex/AuthenticationException.kt

-5
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.coder.gateway.sdk.ex
2+
3+
import java.io.IOException
4+
5+
class AuthenticationResponseException(reason: String) : IOException(reason)
6+
7+
class WorkspaceResponseException(reason: String) : IOException(reason)

src/main/kotlin/com/coder/gateway/views/steps/CoderAuthStepView.kt

+7-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.coder.gateway.models.CoderWorkspacesWizardModel
88
import com.coder.gateway.sdk.CoderCLIManager
99
import com.coder.gateway.sdk.CoderRestClientService
1010
import com.coder.gateway.sdk.OS
11+
import com.coder.gateway.sdk.ex.AuthenticationResponseException
1112
import com.coder.gateway.sdk.getOS
1213
import com.coder.gateway.sdk.toURL
1314
import com.coder.gateway.sdk.withPath
@@ -89,7 +90,12 @@ class CoderAuthStepView(private val nextAction: () -> Unit) : CoderWorkspacesWiz
8990
if (pastedToken.isNullOrBlank()) {
9091
return false
9192
}
92-
coderClient.initClientSession(model.coderURL.toURL(), pastedToken)
93+
try {
94+
coderClient.initClientSession(model.coderURL.toURL(), pastedToken)
95+
} catch (e: AuthenticationResponseException) {
96+
logger.error("Could not authenticate on ${model.coderURL}. Reason $e")
97+
return false
98+
}
9399
model.token = pastedToken
94100
model.buildVersion = coderClient.buildVersion
95101

src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt

+16-13
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,27 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {
110110

111111
cs.launch {
112112
logger.info("Retrieving available IDE's for ${selectedWorkspace.name} workspace...")
113-
try {
114-
val workspaceOS = withContext(Dispatchers.IO) {
113+
val workspaceOS = withContext(Dispatchers.IO) {
114+
try {
115115
RemoteCredentialsHolder().apply {
116116
setHost("coder.${selectedWorkspace.name}")
117117
userName = "coder"
118118
authType = AuthType.OPEN_SSH
119119
}.guessOs
120+
} catch (e: Exception) {
121+
logger.error("Could not resolve any IDE for workspace ${selectedWorkspace.name}. Reason: $e")
122+
null
120123
}
124+
}
125+
if (workspaceOS == null) {
126+
cbIDE.renderer = object : ColoredListCellRenderer<IdeWithStatus>() {
127+
override fun customizeCellRenderer(list: JList<out IdeWithStatus>, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) {
128+
background = UIUtil.getListBackground(isSelected, cellHasFocus)
129+
icon = UIUtil.getBalloonErrorIcon()
130+
append(CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.error.text", selectedWorkspace.name))
131+
}
132+
}
133+
} else {
121134
logger.info("Resolved OS and Arch for ${selectedWorkspace.name} is: $workspaceOS")
122135
val idesWithStatus = IntelliJPlatformProduct.values()
123136
.filter { it.showInGateway }
@@ -130,15 +143,6 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {
130143
ideComboBoxModel.addAll(idesWithStatus)
131144
cbIDE.selectedIndex = 0
132145
}
133-
} catch (e: Exception) {
134-
logger.error("Could not resolve any IDE for workspace ${selectedWorkspace.name}. Reason: $e")
135-
cbIDE.renderer = object : ColoredListCellRenderer<IdeWithStatus>() {
136-
override fun customizeCellRenderer(list: JList<out IdeWithStatus>, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) {
137-
background = UIUtil.getListBackground(isSelected, cellHasFocus)
138-
icon = UIUtil.getBalloonErrorIcon()
139-
append(CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.error.text", selectedWorkspace.name))
140-
}
141-
}
142146
}
143147
}
144148
}
@@ -147,7 +151,6 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {
147151
val selectedIDE = cbIDE.selectedItem ?: return false
148152

149153
cs.launch {
150-
151154
GatewayUI.getInstance().connect(
152155
mapOf(
153156
"type" to "coder",
@@ -203,7 +206,7 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {
203206
background = UIUtil.getListBackground(isSelected, cellHasFocus)
204207
}
205208
} else {
206-
panel { }
209+
panel { }
207210
}
208211
}
209212
}

src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt

+11-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.coder.gateway.sdk.v2.models.Workspace
88
import com.intellij.ide.IdeBundle
99
import com.intellij.openapi.Disposable
1010
import com.intellij.openapi.application.ApplicationManager
11+
import com.intellij.openapi.diagnostic.Logger
1112
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager
1213
import com.intellij.ui.CollectionListModel
1314
import com.intellij.ui.components.JBList
@@ -57,7 +58,12 @@ class CoderWorkspacesStepView : CoderWorkspacesWizardStep, Disposable {
5758

5859
cs.launch {
5960
val workspaceList = withContext(Dispatchers.IO) {
60-
coderClient.workspaces()
61+
try {
62+
coderClient.workspaces()
63+
} catch (e: Exception) {
64+
logger.error("Could not retrieve workspaces for ${coderClient.me.username} on ${coderClient.coderURL}. Reason: $e")
65+
emptyList()
66+
}
6167
}
6268
workspaceList.forEach {
6369
workspaces.add(it)
@@ -77,4 +83,8 @@ class CoderWorkspacesStepView : CoderWorkspacesWizardStep, Disposable {
7783
override fun dispose() {
7884

7985
}
86+
87+
companion object {
88+
val logger = Logger.getInstance(CoderWorkspacesStepView::class.java.simpleName)
89+
}
8090
}

0 commit comments

Comments
 (0)