Skip to content

Commit 18dea22

Browse files
committed
Improve port forwarding
Tool: gitpod/catfood.gitpod.cloud
1 parent a1e89e1 commit 18dea22

File tree

1 file changed

+47
-28
lines changed

1 file changed

+47
-28
lines changed

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

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ abstract class AbstractGitpodPortForwardingService : GitpodPortForwardingService
4747
// Last observed ports list, used to prevent duplicate processing
4848
private var lastPortsList = listOf<PortsStatus>()
4949

50+
// Debounce job for port updates
51+
private var debounceJob: Job? = null
52+
5053
init { start() }
5154

5255
private fun start() {
@@ -98,15 +101,24 @@ abstract class AbstractGitpodPortForwardingService : GitpodPortForwardingService
98101
}
99102

100103
override fun onNext(response: Status.PortsStatusResponse) {
101-
application.invokeLater {
102-
if (syncInProgress.compareAndSet(false, true)) {
103-
try {
104-
syncPortsListWithClient(response)
105-
} finally {
106-
syncInProgress.set(false)
104+
// Cancel previous debounce job if exists
105+
debounceJob?.cancel()
106+
107+
// Create new debounce job
108+
debounceJob = runJob(lifetime) {
109+
delay(300) // 300ms debounce delay
110+
try {
111+
if (syncInProgress.compareAndSet(false, true)) {
112+
try {
113+
syncPortsListWithClient(response)
114+
} finally {
115+
syncInProgress.set(false)
116+
}
117+
} else {
118+
thisLogger().debug("gitpod: Sync already in progress, skipping update")
107119
}
108-
} else {
109-
thisLogger().debug("gitpod: Sync already in progress, skipping update")
120+
} finally {
121+
debounceJob = null
110122
}
111123
}
112124
}
@@ -145,48 +157,55 @@ abstract class AbstractGitpodPortForwardingService : GitpodPortForwardingService
145157
val portsNumbersFromNonServedPorts = portsList.filter { !it.served }.map { it.localPort }
146158

147159
// Clean up unused port lifetimes
148-
val allCurrentPorts = perClientPortForwardingManager.getPorts()
149160
val allPortsToKeep = mutableSetOf<Int>()
150161

151-
// Find ports that need to start forwarding
152162
val servedPortsToStartForwarding = servedPorts.filter {
153163
perClientPortForwardingManager.getPorts(it.localPort).none { p -> p.labels.contains(FORWARDED_PORT_LABEL) }
154164
}
155165

156-
// Find ports that need to start exposing on client
157166
val exposedPortsToStartExposingOnClient = exposedPorts.filter {
158167
perClientPortForwardingManager.getPorts(it.localPort).none { p -> p.labels.contains(EXPOSED_PORT_LABEL) }
159168
}
160169

161-
// Find ports that need to stop forwarding
162170
val forwardedPortsToStopForwarding = perClientPortForwardingManager.getPorts(FORWARDED_PORT_LABEL)
163171
.map { it.hostPortNumber }
164172
.filter { portsNumbersFromNonServedPorts.contains(it) || !portsNumbersFromPortsList.contains(it) }
165173

166-
// Find ports that need to stop exposing on client
167174
val exposedPortsToStopExposingOnClient = perClientPortForwardingManager.getPorts(EXPOSED_PORT_LABEL)
168175
.map { it.hostPortNumber }
169176
.filter { portsNumbersFromNonServedPorts.contains(it) || !portsNumbersFromPortsList.contains(it) }
170177

171-
forwardedPortsToStopForwarding.forEach { stopForwarding(it) }
172-
exposedPortsToStopExposingOnClient.forEach { stopExposingOnClient(it) }
178+
// Process port changes in background
179+
runJob(lifetime) {
180+
try {
181+
// Stop unnecessary ports first
182+
forwardedPortsToStopForwarding.forEach { stopForwarding(it) }
183+
exposedPortsToStopExposingOnClient.forEach { stopExposingOnClient(it) }
184+
185+
// Start necessary ports
186+
servedPortsToStartForwarding.forEach {
187+
startForwarding(it)
188+
allPortsToKeep.add(it.localPort)
189+
}
173190

174-
servedPortsToStartForwarding.forEach {
175-
startForwarding(it)
176-
allPortsToKeep.add(it.localPort)
177-
}
191+
exposedPortsToStartExposingOnClient.forEach {
192+
startExposingOnClient(it)
193+
allPortsToKeep.add(it.localPort)
194+
}
178195

179-
exposedPortsToStartExposingOnClient.forEach {
180-
startExposingOnClient(it)
181-
allPortsToKeep.add(it.localPort)
182-
}
196+
// Update presentation for all ports
197+
application.invokeLater {
198+
portsList.forEach {
199+
updatePortsPresentation(it)
200+
allPortsToKeep.add(it.localPort)
201+
}
202+
}
183203

184-
portsList.forEach {
185-
updatePortsPresentation(it)
186-
allPortsToKeep.add(it.localPort)
204+
cleanupUnusedLifetimes(allPortsToKeep)
205+
} catch (e: Exception) {
206+
thisLogger().error("gitpod: Error during port synchronization", e)
207+
}
187208
}
188-
189-
cleanupUnusedLifetimes(allPortsToKeep)
190209
}
191210

192211
private fun cleanupUnusedLifetimes(portsToKeep: Set<Int>) {

0 commit comments

Comments
 (0)