@@ -26,6 +26,7 @@ import com.jetbrains.toolbox.api.remoteDev.RemoteProvider
26
26
import com.jetbrains.toolbox.api.ui.actions.ActionDelimiter
27
27
import com.jetbrains.toolbox.api.ui.actions.ActionDescription
28
28
import com.jetbrains.toolbox.api.ui.components.UiPage
29
+ import kotlinx.coroutines.CoroutineName
29
30
import kotlinx.coroutines.ExperimentalCoroutinesApi
30
31
import kotlinx.coroutines.Job
31
32
import kotlinx.coroutines.channels.Channel
@@ -87,113 +88,114 @@ class CoderRemoteProvider(
87
88
* workspace is added, reconfigure SSH using the provided cli (including the
88
89
* first time).
89
90
*/
90
- private fun poll (client : CoderRestClient , cli : CoderCLIManager ): Job = context.cs.launch {
91
- var lastPollTime = TimeSource .Monotonic .markNow()
92
- while (isActive) {
93
- try {
94
- context.logger.debug(" Fetching workspace agents from ${client.url} " )
95
- val resolvedEnvironments = client.workspaces().flatMap { ws ->
96
- // Agents are not included in workspaces that are off
97
- // so fetch them separately.
98
- when (ws.latestBuild.status) {
99
- WorkspaceStatus .RUNNING -> ws.latestBuild.resources
100
- else -> emptyList()
101
- }.ifEmpty {
102
- client.resources(ws)
103
- }.flatMap { resource ->
104
- resource.agents?.distinctBy {
105
- // There can be duplicates with coder_agent_instance.
106
- // TODO: Can we just choose one or do they hold
107
- // different information?
108
- it.name
109
- }?.map { agent ->
110
- // If we have an environment already, update that.
111
- val env = CoderRemoteEnvironment (context, client, cli, ws, agent)
112
- lastEnvironments.firstOrNull { it == env }?.let {
113
- it.update(ws, agent)
114
- it
115
- } ? : env
116
- } ? : emptyList()
117
- }
118
- }.toSet()
91
+ private fun poll (client : CoderRestClient , cli : CoderCLIManager ): Job =
92
+ context.cs.launch(CoroutineName (" Workspace Poller" )) {
93
+ var lastPollTime = TimeSource .Monotonic .markNow()
94
+ while (isActive) {
95
+ try {
96
+ context.logger.debug(" Fetching workspace agents from ${client.url} " )
97
+ val resolvedEnvironments = client.workspaces().flatMap { ws ->
98
+ // Agents are not included in workspaces that are off
99
+ // so fetch them separately.
100
+ when (ws.latestBuild.status) {
101
+ WorkspaceStatus .RUNNING -> ws.latestBuild.resources
102
+ else -> emptyList()
103
+ }.ifEmpty {
104
+ client.resources(ws)
105
+ }.flatMap { resource ->
106
+ resource.agents?.distinctBy {
107
+ // There can be duplicates with coder_agent_instance.
108
+ // TODO: Can we just choose one or do they hold
109
+ // different information?
110
+ it.name
111
+ }?.map { agent ->
112
+ // If we have an environment already, update that.
113
+ val env = CoderRemoteEnvironment (context, client, cli, ws, agent)
114
+ lastEnvironments.firstOrNull { it == env }?.let {
115
+ it.update(ws, agent)
116
+ it
117
+ } ? : env
118
+ } ? : emptyList()
119
+ }
120
+ }.toSet()
119
121
120
- // In case we logged out while running the query.
121
- if (! isActive) {
122
- return @launch
123
- }
122
+ // In case we logged out while running the query.
123
+ if (! isActive) {
124
+ return @launch
125
+ }
124
126
125
- // Reconfigure if environments changed.
126
- if (lastEnvironments.size != resolvedEnvironments.size || lastEnvironments != resolvedEnvironments) {
127
- context.logger.info(" Workspaces have changed, reconfiguring CLI: $resolvedEnvironments " )
128
- cli.configSsh(resolvedEnvironments.map { it.asPairOfWorkspaceAndAgent() }.toSet())
129
- }
127
+ // Reconfigure if environments changed.
128
+ if (lastEnvironments.size != resolvedEnvironments.size || lastEnvironments != resolvedEnvironments) {
129
+ context.logger.info(" Workspaces have changed, reconfiguring CLI: $resolvedEnvironments " )
130
+ cli.configSsh(resolvedEnvironments.map { it.asPairOfWorkspaceAndAgent() }.toSet())
131
+ }
130
132
131
- environments.update {
132
- LoadableState .Value (resolvedEnvironments.toList())
133
- }
134
- if (! isInitialized.value) {
135
- context.logger.info(" Environments for ${client.url} are now initialized" )
136
- isInitialized.update {
137
- true
133
+ environments.update {
134
+ LoadableState .Value (resolvedEnvironments.toList())
135
+ }
136
+ if (! isInitialized.value) {
137
+ context.logger.info(" Environments for ${client.url} are now initialized" )
138
+ isInitialized.update {
139
+ true
140
+ }
141
+ }
142
+ lastEnvironments.apply {
143
+ clear()
144
+ addAll(resolvedEnvironments.sortedBy { it.id })
138
145
}
139
- }
140
- lastEnvironments.apply {
141
- clear()
142
- addAll(resolvedEnvironments.sortedBy { it.id })
143
- }
144
146
145
- if (WorkspaceConnectionManager .shouldEstablishWorkspaceConnections) {
146
- WorkspaceConnectionManager .allConnected().forEach { wsId ->
147
- val env = lastEnvironments.firstOrNull() { it.id == wsId }
148
- if (env != null && ! env.isConnected()) {
149
- context.logger.info(" Establishing lost SSH connection for workspace with id $wsId " )
150
- if (! env.startSshConnection()) {
151
- context.logger.info(" Can't establish lost SSH connection for workspace with id $wsId " )
147
+ if (WorkspaceConnectionManager .shouldEstablishWorkspaceConnections) {
148
+ WorkspaceConnectionManager .allConnected().forEach { wsId ->
149
+ val env = lastEnvironments.firstOrNull() { it.id == wsId }
150
+ if (env != null && ! env.isConnected()) {
151
+ context.logger.info(" Establishing lost SSH connection for workspace with id $wsId " )
152
+ if (! env.startSshConnection()) {
153
+ context.logger.info(" Can't establish lost SSH connection for workspace with id $wsId " )
154
+ }
152
155
}
153
156
}
157
+ WorkspaceConnectionManager .reset()
154
158
}
155
- WorkspaceConnectionManager .reset()
156
- }
157
159
158
- WorkspaceConnectionManager .collectStatuses(lastEnvironments)
159
- } catch (_: CancellationException ) {
160
- context.logger.debug(" ${client.url} polling loop canceled" )
161
- break
162
- } catch (ex: Exception ) {
163
- val elapsed = lastPollTime.elapsedNow()
164
- if (elapsed > POLL_INTERVAL * 2 ) {
165
- context.logger.info(" wake-up from an OS sleep was detected" )
166
- } else {
167
- context.logger.error(ex, " workspace polling error encountered" )
168
- if (ex is APIResponseException && ex.isTokenExpired) {
169
- WorkspaceConnectionManager .shouldEstablishWorkspaceConnections = true
170
- close()
171
- context.envPageManager.showPluginEnvironmentsPage()
172
- errorBuffer.add(ex)
173
- break
160
+ WorkspaceConnectionManager .collectStatuses(lastEnvironments)
161
+ } catch (_: CancellationException ) {
162
+ context.logger.debug(" ${client.url} polling loop canceled" )
163
+ break
164
+ } catch (ex: Exception ) {
165
+ val elapsed = lastPollTime.elapsedNow()
166
+ if (elapsed > POLL_INTERVAL * 2 ) {
167
+ context.logger.info(" wake-up from an OS sleep was detected" )
168
+ } else {
169
+ context.logger.error(ex, " workspace polling error encountered" )
170
+ if (ex is APIResponseException && ex.isTokenExpired) {
171
+ WorkspaceConnectionManager .shouldEstablishWorkspaceConnections = true
172
+ close()
173
+ context.envPageManager.showPluginEnvironmentsPage()
174
+ errorBuffer.add(ex)
175
+ break
176
+ }
174
177
}
175
178
}
176
- }
177
179
178
- select {
179
- onTimeout(POLL_INTERVAL ) {
180
- context.logger.debug(" workspace poller waked up by the $POLL_INTERVAL timeout" )
181
- }
182
- triggerSshConfig.onReceive { shouldTrigger ->
183
- if (shouldTrigger) {
184
- context.logger.debug(" workspace poller waked up because it should reconfigure the ssh configurations" )
185
- cli.configSsh(lastEnvironments.map { it.asPairOfWorkspaceAndAgent() }.toSet())
180
+ select {
181
+ onTimeout(POLL_INTERVAL ) {
182
+ context.logger.debug(" workspace poller waked up by the $POLL_INTERVAL timeout" )
186
183
}
187
- }
188
- triggerProviderVisible.onReceive { isCoderProviderVisible ->
189
- if (isCoderProviderVisible) {
190
- context.logger.debug(" workspace poller waked up by Coder Toolbox which is currently visible, fetching latest workspace statuses" )
184
+ triggerSshConfig.onReceive { shouldTrigger ->
185
+ if (shouldTrigger) {
186
+ context.logger.debug(" workspace poller waked up because it should reconfigure the ssh configurations" )
187
+ cli.configSsh(lastEnvironments.map { it.asPairOfWorkspaceAndAgent() }.toSet())
188
+ }
189
+ }
190
+ triggerProviderVisible.onReceive { isCoderProviderVisible ->
191
+ if (isCoderProviderVisible) {
192
+ context.logger.debug(" workspace poller waked up by Coder Toolbox which is currently visible, fetching latest workspace statuses" )
193
+ }
191
194
}
192
195
}
196
+ lastPollTime = TimeSource .Monotonic .markNow()
193
197
}
194
- lastPollTime = TimeSource .Monotonic .markNow()
195
198
}
196
- }
197
199
198
200
/* *
199
201
* Stop polling, clear the client and environments, then go back to the
@@ -221,7 +223,7 @@ class CoderRemoteProvider(
221
223
override val additionalPluginActions: StateFlow <List <ActionDescription >> = MutableStateFlow (
222
224
listOf (
223
225
Action (context.i18n.ptrl(" Create workspace" )) {
224
- context.cs.launch {
226
+ context.cs.launch( CoroutineName ( " Create Workspace Action " )) {
225
227
context.desktop.browse(client?.url?.withPath(" /templates" ).toString()) {
226
228
context.ui.showErrorInfoPopup(it)
227
229
}
@@ -299,7 +301,7 @@ class CoderRemoteProvider(
299
301
visibility
300
302
}
301
303
if (visibility.providerVisible) {
302
- context.cs.launch {
304
+ context.cs.launch( CoroutineName ( " Notify Plugin Visibility " )) {
303
305
triggerProviderVisible.send(true )
304
306
}
305
307
}
@@ -396,11 +398,17 @@ class CoderRemoteProvider(
396
398
context.secrets.lastDeploymentURL = client.url.toString()
397
399
context.secrets.lastToken = client.token ? : " "
398
400
context.secrets.storeTokenFor(client.url, context.secrets.lastToken)
401
+ context.logger.info(" Deployment URL and token were stored and will be available for automatic connection" )
399
402
this .client = client
400
- pollJob?.cancel()
403
+ pollJob?.let {
404
+ it.cancel()
405
+ context.logger.info(" Workspace poll job with reference ${pollJob} was canceled" )
406
+ }
401
407
environments.showLoadingMessage()
402
408
coderHeaderPage.setTitle(context.i18n.pnotr(client.url.toString()))
409
+ context.logger.info(" Displaying ${client.url} in the UI" )
403
410
pollJob = poll(client, cli)
411
+ context.logger.info(" Workspace poll job created with reference $pollJob " )
404
412
context.envPageManager.showPluginEnvironmentsPage()
405
413
}
406
414
0 commit comments