@@ -2,6 +2,7 @@ package com.coder.toolbox
22
33import com.coder.toolbox.browser.BrowserUtil
44import com.coder.toolbox.cli.CoderCLIManager
5+ import com.coder.toolbox.cli.SshCommandProcessHandle
56import com.coder.toolbox.models.WorkspaceAndAgentStatus
67import com.coder.toolbox.sdk.CoderRestClient
78import com.coder.toolbox.sdk.ex.APIResponseException
@@ -20,15 +21,20 @@ import com.jetbrains.toolbox.api.remoteDev.environments.EnvironmentContentsView
2021import com.jetbrains.toolbox.api.remoteDev.states.EnvironmentDescription
2122import com.jetbrains.toolbox.api.remoteDev.states.RemoteEnvironmentState
2223import com.jetbrains.toolbox.api.ui.actions.ActionDescription
24+ import kotlinx.coroutines.Job
2325import kotlinx.coroutines.delay
2426import kotlinx.coroutines.flow.MutableStateFlow
2527import kotlinx.coroutines.flow.update
2628import kotlinx.coroutines.isActive
2729import kotlinx.coroutines.launch
2830import kotlinx.coroutines.withTimeout
31+ import java.io.File
32+ import java.nio.file.Path
2933import kotlin.time.Duration.Companion.minutes
3034import kotlin.time.Duration.Companion.seconds
3135
36+ private val POLL_INTERVAL = 5 .seconds
37+
3238/* *
3339 * Represents an agent and workspace combination.
3440 *
@@ -55,6 +61,9 @@ class CoderRemoteEnvironment(
5561
5662 override val actionsList: MutableStateFlow <List <ActionDescription >> = MutableStateFlow (getAvailableActions())
5763
64+ private val proxyCommandHandle = SshCommandProcessHandle (context)
65+ private var pollJob: Job ? = null
66+
5867 fun asPairOfWorkspaceAndAgent (): Pair <Workspace , WorkspaceAgent > = Pair (workspace, agent)
5968
6069 private fun getAvailableActions (): List <ActionDescription > {
@@ -141,9 +150,37 @@ class CoderRemoteEnvironment(
141150 override fun beforeConnection () {
142151 context.logger.info(" Connecting to $id ..." )
143152 isConnected.update { true }
153+
154+ pollJob = pollNetworkMetrics()
155+ }
156+
157+ private fun pollNetworkMetrics (): Job = context.cs.launch {
158+ context.logger.info(" Starting the network metrics poll job for $id " )
159+ while (isActive) {
160+ context.logger.debug(" Searching SSH command's PID for workspace $id ..." )
161+ val pid = proxyCommandHandle.findByWorkspaceAndAgent(workspace, agent)
162+ if (pid == null ) {
163+ context.logger.debug(" No SSH command PID was found for workspace $id " )
164+ delay(POLL_INTERVAL )
165+ continue
166+ }
167+
168+ val metricsFile = Path .of(context.settingsStore.networkInfoDir, " $pid .json" ).toFile()
169+ if (metricsFile.doesNotExists()) {
170+ context.logger.debug(" No metrics file found at ${metricsFile.absolutePath} for $id " )
171+ delay(POLL_INTERVAL )
172+ continue
173+ }
174+ context.logger.debug(" Loading metrics from ${metricsFile.absolutePath} for $id " )
175+ delay(POLL_INTERVAL )
176+ }
144177 }
145178
179+ private fun File.doesNotExists (): Boolean = ! this .exists()
180+
146181 override fun afterDisconnect () {
182+ context.logger.info(" Stopping the network metrics poll job for $id " )
183+ pollJob?.cancel()
147184 this .connectionRequest.update { false }
148185 isConnected.update { false }
149186 context.logger.info(" Disconnected from $id " )
0 commit comments