@@ -2,6 +2,7 @@ package com.coder.toolbox
2
2
3
3
import com.coder.toolbox.browser.BrowserUtil
4
4
import com.coder.toolbox.cli.CoderCLIManager
5
+ import com.coder.toolbox.cli.SshCommandProcessHandle
5
6
import com.coder.toolbox.models.WorkspaceAndAgentStatus
6
7
import com.coder.toolbox.sdk.CoderRestClient
7
8
import com.coder.toolbox.sdk.ex.APIResponseException
@@ -20,15 +21,20 @@ import com.jetbrains.toolbox.api.remoteDev.environments.EnvironmentContentsView
20
21
import com.jetbrains.toolbox.api.remoteDev.states.EnvironmentDescription
21
22
import com.jetbrains.toolbox.api.remoteDev.states.RemoteEnvironmentState
22
23
import com.jetbrains.toolbox.api.ui.actions.ActionDescription
24
+ import kotlinx.coroutines.Job
23
25
import kotlinx.coroutines.delay
24
26
import kotlinx.coroutines.flow.MutableStateFlow
25
27
import kotlinx.coroutines.flow.update
26
28
import kotlinx.coroutines.isActive
27
29
import kotlinx.coroutines.launch
28
30
import kotlinx.coroutines.withTimeout
31
+ import java.io.File
32
+ import java.nio.file.Path
29
33
import kotlin.time.Duration.Companion.minutes
30
34
import kotlin.time.Duration.Companion.seconds
31
35
36
+ private val POLL_INTERVAL = 5 .seconds
37
+
32
38
/* *
33
39
* Represents an agent and workspace combination.
34
40
*
@@ -55,6 +61,9 @@ class CoderRemoteEnvironment(
55
61
56
62
override val actionsList: MutableStateFlow <List <ActionDescription >> = MutableStateFlow (getAvailableActions())
57
63
64
+ private val proxyCommandHandle = SshCommandProcessHandle (context)
65
+ private var pollJob: Job ? = null
66
+
58
67
fun asPairOfWorkspaceAndAgent (): Pair <Workspace , WorkspaceAgent > = Pair (workspace, agent)
59
68
60
69
private fun getAvailableActions (): List <ActionDescription > {
@@ -141,9 +150,37 @@ class CoderRemoteEnvironment(
141
150
override fun beforeConnection () {
142
151
context.logger.info(" Connecting to $id ..." )
143
152
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
+ }
144
177
}
145
178
179
+ private fun File.doesNotExists (): Boolean = ! this .exists()
180
+
146
181
override fun afterDisconnect () {
182
+ context.logger.info(" Stopping the network metrics poll job for $id " )
183
+ pollJob?.cancel()
147
184
this .connectionRequest.update { false }
148
185
isConnected.update { false }
149
186
context.logger.info(" Disconnected from $id " )
0 commit comments