Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3867a15

Browse files
authored
fix: report errors while running actions (#193)
JetBrains team reported in the past a couple of errors in the log, oneof them being `A workspace build is already active`. The issue can bereproduced if the user hits the `Stop` action for example quite quick.It takes maybe one or two seconds to make rest api request, then for thebackend to enqueue the build and change the workspace action. If we hitthe action buttons really fast then this error could be reproduced.One approach I tried was to disable the action buttons in the contextmenu for the duration the request is executed. But for some reason the"enabled" property is not working in context menu, only when the actionsare rendered on a UI "page".Instead, I decided to refactor the existing code and (also) visuallyreport the errors in the UI screen to make the user aware in some casesthat a job is already running on the backend.Another error reported by JetBrains is a `RejectedExecutionException` inthe rest api client, and from the stack trace it seems the thread poolin the rest client was at some point shutdown.I think it is some sort of race condition, some thread calling shuttingdown the rest api client while the UI thread still executes polling anduser's action. I tried to reproduce the issue with no success, and soI'm improving the logging around plugin de-initialization in the hopethat next time the sequence of events is more helpful.
1 parent7a49167 commit3867a15

File tree

6 files changed

+80
-66
lines changed

6 files changed

+80
-66
lines changed

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
###Fixed
66

77
- token is no longer required when authentication is done via certificates
8+
- errors while running actions are now reported
89

910
##0.6.4 - 2025-09-03
1011

‎src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt‎

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -81,68 +81,61 @@ class CoderRemoteEnvironment(
8181
privatefungetAvailableActions():List<ActionDescription> {
8282
val actions= mutableListOf<Action>()
8383
if (wsRawStatus.canStop()) {
84-
actions.add(Action(context.i18n.ptrl("Open web terminal")) {
85-
context.cs.launch(CoroutineName("Open Web Terminal Action")) {
86-
context.desktop.browse(client.url.withPath("/${workspace.ownerName}/$name/terminal").toString()) {
87-
context.ui.showErrorInfoPopup(it)
88-
}
84+
actions.add(Action(context,"Open web terminal") {
85+
context.desktop.browse(client.url.withPath("/${workspace.ownerName}/$name/terminal").toString()) {
86+
context.ui.showErrorInfoPopup(it)
8987
}
90-
})
88+
}
89+
)
9190
}
9291
actions.add(
93-
Action(context.i18n.ptrl("Open in dashboard")) {
94-
context.cs.launch(CoroutineName("Open in Dashboard Action")) {
95-
context.desktop.browse(
96-
client.url.withPath("/@${workspace.ownerName}/${workspace.name}").toString()
97-
) {
98-
context.ui.showErrorInfoPopup(it)
99-
}
100-
}
101-
})
102-
103-
actions.add(Action(context.i18n.ptrl("View template")) {
104-
context.cs.launch(CoroutineName("View Template Action")) {
105-
context.desktop.browse(client.url.withPath("/templates/${workspace.templateName}").toString()) {
92+
Action(context,"Open in dashboard") {
93+
context.desktop.browse(
94+
client.url.withPath("/@${workspace.ownerName}/${workspace.name}").toString()
95+
) {
10696
context.ui.showErrorInfoPopup(it)
10797
}
10898
}
109-
})
99+
)
100+
101+
actions.add(Action(context,"View template") {
102+
context.desktop.browse(client.url.withPath("/templates/${workspace.templateName}").toString()) {
103+
context.ui.showErrorInfoPopup(it)
104+
}
105+
}
106+
)
110107

111108
if (wsRawStatus.canStart()) {
112109
if (workspace.outdated) {
113-
actions.add(Action(context.i18n.ptrl("Update and start")) {
114-
context.cs.launch(CoroutineName("Update and Start Action")) {
115-
val build= client.updateWorkspace(workspace)
116-
update(workspace.copy(latestBuild= build), agent)
117-
}
118-
})
110+
actions.add(Action(context,"Update and start") {
111+
val build= client.updateWorkspace(workspace)
112+
update(workspace.copy(latestBuild= build), agent)
113+
}
114+
)
119115
}else {
120-
actions.add(Action(context.i18n.ptrl("Start")) {
121-
context.cs.launch(CoroutineName("Start Action")) {
122-
val build= client.startWorkspace(workspace)
123-
update(workspace.copy(latestBuild= build), agent)
116+
actions.add(Action(context,"Start") {
117+
val build= client.startWorkspace(workspace)
118+
update(workspace.copy(latestBuild= build), agent)
124119

125-
}
126-
})
120+
}
121+
)
127122
}
128123
}
129124
if (wsRawStatus.canStop()) {
130125
if (workspace.outdated) {
131-
actions.add(Action(context.i18n.ptrl("Update and restart")) {
132-
context.cs.launch(CoroutineName("Update and Restart Action")) {
133-
val build= client.updateWorkspace(workspace)
134-
update(workspace.copy(latestBuild= build), agent)
135-
}
136-
})
137-
}
138-
actions.add(Action(context.i18n.ptrl("Stop")) {
139-
context.cs.launch(CoroutineName("Stop Action")) {
140-
tryStopSshConnection()
141-
142-
val build= client.stopWorkspace(workspace)
126+
actions.add(Action(context,"Update and restart") {
127+
val build= client.updateWorkspace(workspace)
143128
update(workspace.copy(latestBuild= build), agent)
144129
}
145-
})
130+
)
131+
}
132+
actions.add(Action(context,"Stop") {
133+
tryStopSshConnection()
134+
135+
val build= client.stopWorkspace(workspace)
136+
update(workspace.copy(latestBuild= build), agent)
137+
}
138+
)
146139
}
147140
return actions
148141
}

‎src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt‎

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,10 @@ class CoderRemoteProvider(
202202
* first page.
203203
*/
204204
privatefunlogout() {
205+
context.logger.info("Logging out${client?.me?.username}...")
205206
WorkspaceConnectionManager.reset()
206207
close()
208+
context.logger.info("User${client?.me?.username} logged out successfully")
207209
}
208210

209211
/**
@@ -222,15 +224,13 @@ class CoderRemoteProvider(
222224

223225
overrideval additionalPluginActions:StateFlow<List<ActionDescription>>=MutableStateFlow(
224226
listOf(
225-
Action(context.i18n.ptrl("Create workspace")) {
226-
context.cs.launch(CoroutineName("Create Workspace Action")) {
227-
context.desktop.browse(client?.url?.withPath("/templates").toString()) {
228-
context.ui.showErrorInfoPopup(it)
229-
}
227+
Action(context,"Create workspace") {
228+
context.desktop.browse(client?.url?.withPath("/templates").toString()) {
229+
context.ui.showErrorInfoPopup(it)
230230
}
231231
},
232232
CoderDelimiter(context.i18n.pnotr("")),
233-
Action(context.i18n.ptrl("Settings")) {
233+
Action(context,"Settings") {
234234
context.ui.showUiPage(settingsPage)
235235
},
236236
)
@@ -246,12 +246,16 @@ class CoderRemoteProvider(
246246
it.cancel()
247247
context.logger.info("Cancelled workspace poll job${pollJob.toString()}")
248248
}
249-
client?.close()
249+
client?.let {
250+
it.close()
251+
context.logger.info("REST API client closed and resources released")
252+
}
253+
client=null
250254
lastEnvironments.clear()
251255
environments.value=LoadableState.Value(emptyList())
252256
isInitialized.update {false }
253-
client=null
254257
CoderCliSetupWizardState.goToFirstStep()
258+
context.logger.info("Coder plugin is now closed")
255259
}
256260

257261
overrideval svgIcon:SvgIcon=
@@ -319,12 +323,12 @@ class CoderRemoteProvider(
319323
uri,
320324
shouldDoAutoSetup()
321325
) { restClient, cli->
322-
// stop polling and de-initialize resources
326+
context.logger.info("Stopping workspace polling and de-initializing resources")
323327
close()
324328
isInitialized.update {
325329
false
326330
}
327-
// startinitialization with the new settings
331+
context.logger.info("Startinginitialization with the new settings")
328332
this@CoderRemoteProvider.client= restClient
329333
coderHeaderPage.setTitle(context.i18n.pnotr(restClient.url.toString()))
330334

‎src/main/kotlin/com/coder/toolbox/views/CoderCliSetupWizardPage.kt‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ class CoderCliSetupWizardPage(
2424
)->Unit,
2525
) : CoderPage(MutableStateFlow(context.i18n.ptrl("Setting upCoder")),false) {
2626
privateval shouldAutoSetup=MutableStateFlow(initialAutoSetup)
27-
privateval settingsAction=Action(context.i18n.ptrl("Settings"), actionBlock= {
27+
privateval settingsAction=Action(context,"Settings") {
2828
context.ui.showUiPage(settingsPage)
29-
})
29+
}
3030

3131
privateval deploymentUrlStep=DeploymentUrlStep(context, visibilityState)
3232
privateval tokenStep=TokenStep(context)
@@ -60,7 +60,7 @@ class CoderCliSetupWizardPage(
6060
}
6161
actionButtons.update {
6262
listOf(
63-
Action(context.i18n.ptrl("Next"), closesPage=false, actionBlock= {
63+
Action(context,"Next", closesPage=false, actionBlock= {
6464
if (deploymentUrlStep.onNext()) {
6565
displaySteps()
6666
}
@@ -77,13 +77,13 @@ class CoderCliSetupWizardPage(
7777
}
7878
actionButtons.update {
7979
listOf(
80-
Action(context.i18n.ptrl("Connect"), closesPage=false, actionBlock= {
80+
Action(context,"Connect", closesPage=false, actionBlock= {
8181
if (tokenStep.onNext()) {
8282
displaySteps()
8383
}
8484
}),
8585
settingsAction,
86-
Action(context.i18n.ptrl("Back"), closesPage=false, actionBlock= {
86+
Action(context,"Back", closesPage=false, actionBlock= {
8787
tokenStep.onBack()
8888
displaySteps()
8989
})
@@ -99,7 +99,7 @@ class CoderCliSetupWizardPage(
9999
actionButtons.update {
100100
listOf(
101101
settingsAction,
102-
Action(context.i18n.ptrl("Back"), closesPage=false, actionBlock= {
102+
Action(context,"Back", closesPage=false, actionBlock= {
103103
connectStep.onBack()
104104
shouldAutoSetup.update {
105105
false

‎src/main/kotlin/com/coder/toolbox/views/CoderPage.kt‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
packagecom.coder.toolbox.views
22

3+
importcom.coder.toolbox.CoderToolboxContext
4+
importcom.coder.toolbox.sdk.ex.APIResponseException
35
importcom.jetbrains.toolbox.api.core.ui.icons.SvgIcon
46
importcom.jetbrains.toolbox.api.core.ui.icons.SvgIcon.IconType
57
importcom.jetbrains.toolbox.api.localization.LocalizableString
68
importcom.jetbrains.toolbox.api.ui.actions.RunnableActionDescription
79
importcom.jetbrains.toolbox.api.ui.components.UiPage
10+
importkotlinx.coroutines.CoroutineName
811
importkotlinx.coroutines.flow.MutableStateFlow
912
importkotlinx.coroutines.flow.update
13+
importkotlinx.coroutines.launch
1014

1115
/**
1216
* Base page that handles the icon, displaying error notifications, and
@@ -48,15 +52,27 @@ abstract class CoderPage(
4852
* An action that simply runs the provided callback.
4953
*/
5054
classAction(
51-
description:LocalizableString,
55+
privatevalcontext:CoderToolboxContext,
56+
privatevaldescription:String,
5257
closesPage:Boolean =false,
5358
enabled: ()->Boolean = {true },
54-
privatevalactionBlock: ()->Unit,
59+
privatevalactionBlock:suspend()->Unit,
5560
) : RunnableActionDescription {
56-
overrideval label:LocalizableString= description
61+
overrideval label:LocalizableString=context.i18n.ptrl(description)
5762
overrideval shouldClosePage:Boolean= closesPage
5863
overrideval isEnabled:Boolean= enabled()
5964
overridefunrun() {
60-
actionBlock()
65+
context.cs.launch(CoroutineName("$description Action")) {
66+
try {
67+
actionBlock()
68+
}catch (ex:Exception) {
69+
val textError=if (exisAPIResponseException) {
70+
if (!ex.reason.isNullOrBlank()) {
71+
ex.reason
72+
}else ex.message
73+
}else ex.message
74+
context.logAndShowError("Error while running `$description`", textError?:"", ex)
75+
}
76+
}
6177
}
6278
}

‎src/main/kotlin/com/coder/toolbox/views/CoderSettingsPage.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class CoderSettingsPage(private val context: CoderToolboxContext, triggerSshConf
116116

117117
overrideval actionButtons:StateFlow<List<RunnableActionDescription>>=MutableStateFlow(
118118
listOf(
119-
Action(context.i18n.ptrl("Save"), closesPage=true) {
119+
Action(context,"Save", closesPage=true) {
120120
context.settingsStore.updateBinarySource(binarySourceField.contentState.value)
121121
context.settingsStore.updateBinaryDirectory(binaryDirectoryField.contentState.value)
122122
context.settingsStore.updateDataDirectory(dataDirectoryField.contentState.value)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp