@@ -26,7 +26,8 @@ import java.util.*
2626import java.util.concurrent.CompletableFuture
2727import java.util.concurrent.ConcurrentHashMap
2828import java.util.concurrent.atomic.AtomicReference
29- import java.util.concurrent.Semaphore
29+ import kotlinx.coroutines.sync.Mutex
30+ import kotlinx.coroutines.sync.withLock
3031
3132@Suppress(" UnstableApiUsage" )
3233abstract class AbstractGitpodPortForwardingService : GitpodPortForwardingService {
@@ -52,11 +53,11 @@ abstract class AbstractGitpodPortForwardingService : GitpodPortForwardingService
5253 private var debounceJob: Job ? = null
5354
5455 // Batch size for port operations
55- private val BATCH_SIZE = 10
56- private val BATCH_DELAY = 100
56+ private val batchSize = 10
57+ private val batchDelay = 100L
5758
58- // Semaphore to limit concurrent operations
59- private val operationSemaphore = Semaphore ( 10 )
59+ // Mutex to limit concurrent operations
60+ private val operationMutex = Mutex ( )
6061
6162 init { start() }
6263
@@ -186,53 +187,49 @@ abstract class AbstractGitpodPortForwardingService : GitpodPortForwardingService
186187 // Process port changes in background with batching
187188 runJob(lifetime) {
188189 try {
189- forwardedPortsToStopForwarding.chunked(BATCH_SIZE ).forEach { batch ->
190+ forwardedPortsToStopForwarding.chunked(batchSize ).forEach { batch ->
190191 batch.forEach { port ->
191- operationSemaphore.withPermit {
192- stopForwarding(port)
193- }
192+ operationMutex.withLock { stopForwarding(port) }
194193 }
195- delay(100 ) // Add delay between batches
194+ delay(batchDelay)
196195 }
197196
198- exposedPortsToStopExposingOnClient.chunked(BATCH_SIZE ).forEach { batch ->
197+ exposedPortsToStopExposingOnClient.chunked(batchSize ).forEach { batch ->
199198 batch.forEach { port ->
200- operationSemaphore.withPermit {
201- stopExposingOnClient(port)
202- }
199+ operationMutex.withLock { stopExposingOnClient(port) }
203200 }
204- delay(BATCH_DELAY )
201+ delay(batchDelay )
205202 }
206203
207- servedPortsToStartForwarding.chunked(BATCH_SIZE ).forEach { batch ->
204+ servedPortsToStartForwarding.chunked(batchSize ).forEach { batch ->
208205 batch.forEach { port ->
209- operationSemaphore.withPermit {
206+ operationMutex.withLock {
210207 startForwarding(port)
211208 allPortsToKeep.add(port.localPort)
212209 }
213210 }
214- delay(BATCH_DELAY )
211+ delay(batchDelay )
215212 }
216213
217- exposedPortsToStartExposingOnClient.chunked(BATCH_SIZE ).forEach { batch ->
214+ exposedPortsToStartExposingOnClient.chunked(batchSize ).forEach { batch ->
218215 batch.forEach { port ->
219- operationSemaphore.withPermit {
216+ operationMutex.withLock {
220217 startExposingOnClient(port)
221218 allPortsToKeep.add(port.localPort)
222219 }
223220 }
224- delay(BATCH_DELAY )
221+ delay(batchDelay )
225222 }
226223
227224 // Update presentation for all ports in batches
228- portsList.chunked(BATCH_SIZE ).forEach { batch ->
225+ portsList.chunked(batchSize ).forEach { batch ->
229226 application.invokeLater {
230227 batch.forEach {
231228 updatePortsPresentation(it)
232229 allPortsToKeep.add(it.localPort)
233230 }
234231 }
235- delay(BATCH_DELAY )
232+ delay(batchDelay )
236233 }
237234
238235 cleanupUnusedLifetimes(allPortsToKeep)
0 commit comments