@@ -10,14 +10,20 @@ import com.coder.toolbox.sdk.v2.models.Workspace
1010import com.coder.toolbox.sdk.v2.models.WorkspaceAgent
1111import com.coder.toolbox.sdk.v2.models.WorkspaceStatus
1212import com.coder.toolbox.settings.CoderSettings
13+ import kotlinx.coroutines.TimeoutCancellationException
14+ import kotlinx.coroutines.delay
1315import kotlinx.coroutines.flow.StateFlow
1416import kotlinx.coroutines.flow.filter
1517import kotlinx.coroutines.launch
18+ import kotlinx.coroutines.time.withTimeout
1619import kotlinx.coroutines.yield
1720import okhttp3.OkHttpClient
1821import java.net.HttpURLConnection
1922import java.net.URI
2023import java.net.URL
24+ import kotlin.time.Duration.Companion.minutes
25+ import kotlin.time.Duration.Companion.seconds
26+ import kotlin.time.toJavaDuration
2127
2228open class CoderProtocolHandler (
2329 private val context : CoderToolboxContext ,
@@ -81,29 +87,27 @@ open class CoderProtocolHandler(
8187
8288 when (workspace.latestBuild.status) {
8389 WorkspaceStatus .PENDING , WorkspaceStatus .STARTING ->
84- // TODO: Wait for the workspace to turn on.
85- throw IllegalArgumentException (
86- " The workspace \" $workspaceName \" is ${
87- workspace.latestBuild.status.toString().lowercase()
88- } ; please wait then try again" ,
89- )
90+ if (restClient.waitForReady(workspace) != true ) {
91+ context.logger.error(" $workspaceName from $deploymentURL could not be ready on time" )
92+ context.ui.showErrorInfoPopup(MissingArgumentException (" Can't handle URI because workspace $workspaceName could not be ready on time" ))
93+ return
94+ }
9095
9196 WorkspaceStatus .STOPPING , WorkspaceStatus .STOPPED ,
92- WorkspaceStatus .CANCELING , WorkspaceStatus .CANCELED ,
93- ->
94- // TODO: Turn on the workspace.
95- throw IllegalArgumentException (
96- " The workspace \" $workspaceName \" is ${
97- workspace.latestBuild.status.toString().lowercase()
98- } ; please start the workspace and try again " ,
99- )
97+ WorkspaceStatus .CANCELING , WorkspaceStatus .CANCELED -> {
98+ restClient.startWorkspace(workspace)
99+ if (restClient.waitForReady(workspace) != true ) {
100+ context.logger.error( " $workspaceName from $deploymentURL could not be started on time " )
101+ context.ui.showErrorInfoPopup( MissingArgumentException ( " Can't handle URI because workspace $workspaceName could not be started on time " ))
102+ return
103+ }
104+ }
100105
101- WorkspaceStatus .FAILED , WorkspaceStatus .DELETING , WorkspaceStatus .DELETED ->
102- throw IllegalArgumentException (
103- " The workspace \" $workspaceName \" is ${
104- workspace.latestBuild.status.toString().lowercase()
105- } ; unable to connect" ,
106- )
106+ WorkspaceStatus .FAILED , WorkspaceStatus .DELETING , WorkspaceStatus .DELETED -> {
107+ context.logger.error(" Unable to connect to $workspaceName from $deploymentURL " )
108+ context.ui.showErrorInfoPopup(MissingArgumentException (" Can't handle URI because because we're unable to connect to workspace $workspaceName " ))
109+ return
110+ }
107111
108112 WorkspaceStatus .RUNNING -> Unit // All is well
109113 }
@@ -157,6 +161,21 @@ open class CoderProtocolHandler(
157161 }
158162 }
159163
164+ private suspend fun CoderRestClient.waitForReady (workspace : Workspace ): Boolean {
165+ var status = workspace.latestBuild.status
166+ try {
167+ withTimeout(2 .minutes.toJavaDuration()) {
168+ while (status != WorkspaceStatus .RUNNING ) {
169+ delay(1 .seconds)
170+ status = this @waitForReady.workspace(workspace.id).latestBuild.status
171+ }
172+ }
173+ return true
174+ } catch (_: TimeoutCancellationException ) {
175+ return false
176+ }
177+ }
178+
160179 private suspend fun askUrl (): String? {
161180 context.ui.showWindow()
162181 context.envPageManager.showPluginEnvironmentsPage(false )
0 commit comments