Skip to content

Commit 5b7f3e9

Browse files
committed
impl: support for uri handling (2)
- reworked the main env provider to be able to close all existing resources and re-initialize with a different deployment - the re-initialization is needed in order to navigate to an env page with the targeted workspace. If the workspace is not from the current deployment there will be no env page to navigate to.
1 parent 0661a8d commit 5b7f3e9

File tree

3 files changed

+36
-16
lines changed

3 files changed

+36
-16
lines changed

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

+14-7
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,12 @@ class CoderRemoteProvider(
4747
private var pollJob: Job? = null
4848
private var lastEnvironments: Set<CoderRemoteEnvironment>? = null
4949

50-
private val isInitialized: MutableStateFlow<Boolean> = MutableStateFlow(false)
51-
5250
// Create our services from the Toolbox ones.
5351
private val settingsService = CoderSettingsService(context.settingsStore)
5452
private val settings: CoderSettings = CoderSettings(settingsService, context.logger)
5553
private val secrets: CoderSecretsService = CoderSecretsService(context.secretsStore)
5654
private val settingsPage: CoderSettingsPage = CoderSettingsPage(context, settingsService)
5755
private val dialogUi = DialogUi(context, settings)
58-
private val linkHandler = CoderProtocolHandler(context, settings, httpClient, dialogUi, isInitialized)
5956

6057
// The REST client, if we are signed in
6158
private var client: CoderRestClient? = null
@@ -67,6 +64,9 @@ class CoderRemoteProvider(
6764

6865
// On the first load, automatically log in if we can.
6966
private var firstRun = true
67+
private val isInitialized: MutableStateFlow<Boolean> = MutableStateFlow(false)
68+
private var coderHeaderPager = NewEnvironmentPage(context, context.i18n.pnotr(getDeploymentURL()?.first ?: ""))
69+
private val linkHandler = CoderProtocolHandler(context, settings, httpClient, dialogUi, isInitialized)
7070
override val environments: MutableStateFlow<LoadableState<List<RemoteProviderEnvironment>>> = MutableStateFlow(
7171
LoadableState.Value(emptyList())
7272
)
@@ -176,9 +176,10 @@ class CoderRemoteProvider(
176176
*/
177177
override fun close() {
178178
pollJob?.cancel()
179-
client = null
179+
client?.close()
180180
lastEnvironments = null
181181
environments.value = LoadableState.Value(emptyList())
182+
isInitialized.update { false }
182183
}
183184

184185
override val svgIcon: SvgIcon =
@@ -213,8 +214,7 @@ class CoderRemoteProvider(
213214
* Just displays the deployment URL at the moment, but we could use this as
214215
* a form for creating new environments.
215216
*/
216-
override fun getNewEnvironmentUiPage(): UiPage =
217-
NewEnvironmentPage(context, context.i18n.pnotr(getDeploymentURL()?.first ?: ""))
217+
override fun getNewEnvironmentUiPage(): UiPage = coderHeaderPager
218218

219219
/**
220220
* We always show a list of environments.
@@ -234,7 +234,14 @@ class CoderRemoteProvider(
234234
*/
235235
override suspend fun handleUri(uri: URI) {
236236
val params = uri.toQueryParameters()
237-
linkHandler.handle(params)
237+
linkHandler.handle(params) { restClient, cli ->
238+
// stop polling and de-initialize resources
239+
close()
240+
// start initialization with the new settings
241+
this@CoderRemoteProvider.client = restClient
242+
coderHeaderPager = NewEnvironmentPage(context, context.i18n.pnotr(restClient.url.toString()))
243+
poll(restClient, cli)
244+
}
238245
}
239246

240247
/**

src/main/kotlin/com/coder/toolbox/sdk/CoderRestClient.kt

+8
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,12 @@ open class CoderRestClient(
272272
}
273273
return buildResponse.body()!!
274274
}
275+
276+
fun close() {
277+
httpClient.apply {
278+
dispatcher.executorService.shutdown()
279+
connectionPool.evictAll()
280+
cache?.close()
281+
}
282+
}
275283
}

src/main/kotlin/com/coder/toolbox/util/CoderProtocolHandler.kt

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.coder.toolbox.util
22

33
import com.coder.toolbox.CoderToolboxContext
4+
import com.coder.toolbox.cli.CoderCLIManager
45
import com.coder.toolbox.cli.ensureCLI
56
import com.coder.toolbox.models.WorkspaceAndAgentStatus
67
import com.coder.toolbox.plugin.PluginManager
@@ -33,7 +34,10 @@ open class CoderProtocolHandler(
3334
* Throw if required arguments are not supplied or the workspace is not in a
3435
* connectable state.
3536
*/
36-
suspend fun handle(parameters: Map<String, String>) {
37+
suspend fun handle(
38+
parameters: Map<String, String>,
39+
onReinitialize: suspend (CoderRestClient, CoderCLIManager) -> Unit
40+
) {
3741
val deploymentURL =
3842
parameters.url() ?: dialogUi.ask(
3943
context.i18n.ptrl("Deployment URL"),
@@ -49,7 +53,7 @@ open class CoderProtocolHandler(
4953
} else {
5054
null
5155
}
52-
val client = try {
56+
val restClient = try {
5357
authenticate(deploymentURL, queryToken)
5458
} catch (ex: MissingArgumentException) {
5559
throw MissingArgumentException("Query parameter \"$TOKEN\" is missing", ex)
@@ -59,7 +63,7 @@ open class CoderProtocolHandler(
5963
val workspaceName =
6064
parameters.workspace() ?: throw MissingArgumentException("Query parameter \"$WORKSPACE\" is missing")
6165

62-
val workspaces = client.workspaces()
66+
val workspaces = restClient.workspaces()
6367
val workspace =
6468
workspaces.firstOrNull {
6569
it.name == workspaceName
@@ -117,23 +121,24 @@ open class CoderProtocolHandler(
117121
ensureCLI(
118122
context,
119123
deploymentURL.toURL(),
120-
client.buildInfo().version,
124+
restClient.buildInfo().version,
121125
settings
122126
)
123127

124128
// We only need to log in if we are using token-based auth.
125-
if (client.token != null) {
129+
if (restClient.token != null) {
126130
context.logger.info("Authenticating Coder CLI...")
127-
cli.login(client.token)
131+
cli.login(restClient.token)
128132
}
129133

130134
context.logger.info("Configuring Coder CLI...")
131-
cli.configSsh(client.agentNames(workspaces))
135+
cli.configSsh(restClient.agentNames(workspaces))
132136

133-
isInitialized.waitForTrue()
137+
onReinitialize(restClient, cli)
134138
context.cs.launch {
135139
context.ui.showWindow()
136-
yield()
140+
context.envPageManager.showPluginEnvironmentsPage(true)
141+
isInitialized.waitForTrue()
137142
context.envPageManager.showEnvironmentPage("${workspace.name}.${agent.name}", false)
138143
// without a yield or a delay(0) the env page does not show up. My assumption is that
139144
// the coroutine is finishing too fast without giving enough time to compose main thread

0 commit comments

Comments
 (0)