Skip to content

Commit bdd2bb6

Browse files
committed
Avoid shutting down terminals when closing JetBrains Client
Instead, close the widgets and reopen then when the client joins again.
1 parent ca94fa5 commit bdd2bb6

File tree

1 file changed

+41
-24
lines changed

1 file changed

+41
-24
lines changed

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodTerminalService.kt

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44

55
package io.gitpod.jetbrains.remote
66

7+
import com.intellij.openapi.Disposable
78
import com.intellij.openapi.diagnostic.thisLogger
89
import com.intellij.openapi.project.Project
10+
import com.intellij.openapi.rd.defineNestedLifetime
11+
import com.intellij.remoteDev.util.onTerminationOrNow
912
import com.intellij.util.application
1013
import com.jediterm.terminal.ui.TerminalWidget
1114
import com.jediterm.terminal.ui.TerminalWidgetListener
15+
import com.jetbrains.rd.framework.util.launch
1216
import com.jetbrains.rdserver.terminal.BackendTerminalManager
1317
import io.gitpod.supervisor.api.Status
1418
import io.gitpod.supervisor.api.StatusServiceGrpc
@@ -17,18 +21,18 @@ import io.gitpod.supervisor.api.TerminalServiceGrpc
1721
import io.grpc.StatusRuntimeException
1822
import io.grpc.stub.ClientCallStreamObserver
1923
import io.grpc.stub.ClientResponseObserver
24+
import kotlinx.coroutines.delay
25+
import kotlinx.coroutines.future.await
26+
import kotlinx.coroutines.guava.await
2027
import org.jetbrains.plugins.terminal.ShellTerminalWidget
2128
import org.jetbrains.plugins.terminal.TerminalView
2229
import java.util.*
2330
import java.util.concurrent.CompletableFuture
2431
import java.util.concurrent.ExecutionException
25-
import java.util.concurrent.TimeUnit
26-
27-
class GitpodTerminalService(project: Project) {
28-
private companion object {
29-
var hasStarted = false
30-
}
3132

33+
@Suppress("UnstableApiUsage")
34+
class GitpodTerminalService(project: Project): Disposable {
35+
private val lifetime = defineNestedLifetime()
3236
private val terminalView = TerminalView.getInstance(project)
3337
private val backendTerminalManager = BackendTerminalManager.getInstance(project)
3438
private val terminalServiceFutureStub = TerminalServiceGrpc.newFutureStub(GitpodManager.supervisorChannel)
@@ -39,12 +43,12 @@ class GitpodTerminalService(project: Project) {
3943
start()
4044
}
4145

42-
private fun start() {
43-
if (application.isHeadlessEnvironment || hasStarted) return
46+
override fun dispose() = Unit
4447

45-
hasStarted = true
48+
private fun start() {
49+
if (application.isHeadlessEnvironment) return
4650

47-
application.executeOnPooledThread {
51+
lifetime.launch {
4852
val terminals = getSupervisorTerminalsList()
4953
val tasks = getSupervisorTasksList()
5054

@@ -95,7 +99,7 @@ class GitpodTerminalService(project: Project) {
9599
}
96100
}
97101

98-
private tailrec fun getSupervisorTasksList(): List<Status.TaskStatus> {
102+
private tailrec suspend fun getSupervisorTasksList(): List<Status.TaskStatus> {
99103
var tasksList: List<Status.TaskStatus>? = null
100104

101105
try {
@@ -124,7 +128,7 @@ class GitpodTerminalService(project: Project) {
124128

125129
statusServiceStub.tasksStatus(taskStatusRequest, taskStatusResponseObserver)
126130

127-
tasksList = completableFuture.get()
131+
tasksList = completableFuture.await()
128132
} catch (throwable: Throwable) {
129133
if (throwable is InterruptedException) {
130134
throw throwable
@@ -140,20 +144,20 @@ class GitpodTerminalService(project: Project) {
140144
return if (tasksList != null) {
141145
tasksList
142146
} else {
143-
TimeUnit.SECONDS.sleep(1)
147+
delay(1000)
144148
getSupervisorTasksList()
145149
}
146150
}
147151

148-
private tailrec fun getSupervisorTerminalsList(): List<TerminalOuterClass.Terminal> {
152+
private tailrec suspend fun getSupervisorTerminalsList(): List<TerminalOuterClass.Terminal> {
149153
var terminalsList: List<TerminalOuterClass.Terminal>? = null
150154

151155
try {
152156
val listTerminalsRequest = TerminalOuterClass.ListTerminalsRequest.newBuilder().build()
153157

154158
val listTerminalsResponseFuture = terminalServiceFutureStub.list(listTerminalsRequest)
155159

156-
val listTerminalsResponse = listTerminalsResponseFuture.get()
160+
val listTerminalsResponse = listTerminalsResponseFuture.await()
157161

158162
terminalsList = listTerminalsResponse.terminalsList
159163
} catch (throwable: Throwable) {
@@ -171,7 +175,7 @@ class GitpodTerminalService(project: Project) {
171175
return if (terminalsList != null) {
172176
terminalsList
173177
} else {
174-
TimeUnit.SECONDS.sleep(1)
178+
delay(1000)
175179
getSupervisorTerminalsList()
176180
}
177181
}
@@ -182,6 +186,8 @@ class GitpodTerminalService(project: Project) {
182186
"gp tasks attach ${supervisorTerminal.alias}"
183187
) ?: return
184188

189+
closeTerminalWidgetWhenClientGetsClosed(shellTerminalWidget)
190+
185191
exitTaskWhenTerminalWidgetGetsClosed(supervisorTerminal, shellTerminalWidget)
186192

187193
listenForTaskTerminationAndTitleChanges(supervisorTerminal, shellTerminalWidget)
@@ -190,7 +196,7 @@ class GitpodTerminalService(project: Project) {
190196
private fun listenForTaskTerminationAndTitleChanges(
191197
supervisorTerminal: TerminalOuterClass.Terminal,
192198
shellTerminalWidget: ShellTerminalWidget
193-
) = application.executeOnPooledThread {
199+
) = lifetime.launch {
194200
var hasOpenSessions = true
195201

196202
while (hasOpenSessions) {
@@ -241,7 +247,7 @@ class GitpodTerminalService(project: Project) {
241247
terminalServiceStub.listen(listenTerminalRequest, listenTerminalResponseObserver)
242248

243249
try {
244-
completableFuture.get()
250+
completableFuture.await()
245251
} catch (throwable: Throwable) {
246252
if (
247253
throwable is StatusRuntimeException ||
@@ -259,7 +265,7 @@ class GitpodTerminalService(project: Project) {
259265
"'${supervisorTerminal.title}' terminal. Trying again in one second.", throwable)
260266
}
261267

262-
TimeUnit.SECONDS.sleep(1)
268+
delay(1000)
263269
}
264270
}
265271

@@ -270,12 +276,23 @@ class GitpodTerminalService(project: Project) {
270276
@Suppress("ObjectLiteralToLambda")
271277
shellTerminalWidget.addListener(object : TerminalWidgetListener {
272278
override fun allSessionsClosed(widget: TerminalWidget) {
273-
terminalServiceFutureStub.shutdown(
274-
TerminalOuterClass.ShutdownTerminalRequest.newBuilder()
275-
.setAlias(supervisorTerminal.alias)
276-
.build()
277-
)
279+
lifetime.launch {
280+
delay(5000)
281+
terminalServiceFutureStub.shutdown(
282+
TerminalOuterClass.ShutdownTerminalRequest.newBuilder()
283+
.setAlias(supervisorTerminal.alias)
284+
.build()
285+
)
286+
}
278287
}
279288
})
280289
}
290+
291+
private fun closeTerminalWidgetWhenClientGetsClosed(
292+
shellTerminalWidget: ShellTerminalWidget
293+
) {
294+
lifetime.onTerminationOrNow {
295+
shellTerminalWidget.close()
296+
}
297+
}
281298
}

0 commit comments

Comments
 (0)