Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.

Commit 23bd77d

Browse files
committed
refactor(NettyServer): replace mutableObjectList with Caffeine cache and ConcurrentLinkedQueue for improved client management
1 parent b507429 commit 23bd77d

File tree

1 file changed

+28
-33
lines changed
  • surf-cloud-standalone/src/main/kotlin/dev/slne/surf/cloud/standalone/netty/server

1 file changed

+28
-33
lines changed

surf-cloud-standalone/src/main/kotlin/dev/slne/surf/cloud/standalone/netty/server/NettyServerImpl.kt

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package dev.slne.surf.cloud.standalone.netty.server
22

3-
import dev.slne.surf.cloud.api.common.util.mutableObjectListOf
4-
import dev.slne.surf.cloud.api.common.util.synchronize
3+
import com.github.benmanes.caffeine.cache.Caffeine
4+
import dev.slne.surf.cloud.api.common.util.toObjectList
55
import dev.slne.surf.cloud.core.common.config.cloudConfig
66
import dev.slne.surf.cloud.core.common.netty.network.DisconnectReason
77
import dev.slne.surf.cloud.core.common.netty.network.DisconnectionDetails
@@ -16,8 +16,6 @@ import io.netty.channel.epoll.Epoll
1616
import io.netty.channel.unix.DomainSocketAddress
1717
import kotlinx.coroutines.Dispatchers
1818
import kotlinx.coroutines.runBlocking
19-
import kotlinx.coroutines.sync.Mutex
20-
import kotlinx.coroutines.sync.withLock
2119
import kotlinx.coroutines.withContext
2220
import org.springframework.beans.factory.DisposableBean
2321
import org.springframework.beans.factory.InitializingBean
@@ -27,6 +25,7 @@ import org.springframework.stereotype.Component
2725
import java.net.InetAddress
2826
import java.net.InetSocketAddress
2927
import java.net.SocketAddress
28+
import java.util.concurrent.ConcurrentLinkedQueue
3029
import java.util.concurrent.TimeUnit
3130
import kotlin.system.measureTimeMillis
3231

@@ -39,9 +38,10 @@ class NettyServerImpl : InitializingBean, DisposableBean {
3938
private var port = -1
4039

4140
val connection by lazy { ServerConnectionListener(this) }
42-
private val clients = mutableObjectListOf<ServerClientImpl>()
43-
private val clientsLock = Mutex()
44-
private val schedules = mutableObjectListOf<() -> Unit>().synchronize()
41+
private val clients = Caffeine.newBuilder()
42+
.build<String, ServerClientImpl>()
43+
44+
private val schedules = ConcurrentLinkedQueue<() -> Unit>()
4545

4646
@Volatile
4747
private var running = false
@@ -114,9 +114,14 @@ class NettyServerImpl : InitializingBean, DisposableBean {
114114
CloudTickHook.tick()
115115
connection.connections.forEach { it.tick() }
116116
connection.tick()
117-
schedules.removeAll { function ->
118-
function()
119-
true
117+
while (true) {
118+
val function = schedules.poll() ?: break
119+
try {
120+
function()
121+
} catch (e: Exception) {
122+
log.atSevere()
123+
.log("Error during scheduled function execution", e)
124+
}
120125
}
121126
}
122127
CloudTickReporter.tick(duration.toDouble())
@@ -127,20 +132,16 @@ class NettyServerImpl : InitializingBean, DisposableBean {
127132
}
128133

129134
suspend fun registerClient(client: ServerClientImpl, proxy: Boolean) {
130-
clientsLock.withLock {
131-
if (clients.any { it.serverName == client.serverName }) {
132-
log.atSevere()
133-
.log("Client with name ${client.serverName} already exists")
134-
client.connection.disconnect(
135-
DisconnectionDetails(
136-
DisconnectReason.CLIENT_NAME_ALREADY_EXISTS,
137-
client.serverName
138-
)
135+
if (clients.asMap().putIfAbsent(client.serverName, client) != null) {
136+
log.atSevere()
137+
.log("Client with name ${client.serverName} already exists")
138+
client.connection.disconnect(
139+
DisconnectionDetails(
140+
DisconnectReason.CLIENT_NAME_ALREADY_EXISTS,
141+
client.serverName
139142
)
140-
return
141-
}
142-
143-
clients.add(client)
143+
)
144+
return
144145
}
145146

146147
log.atInfo().log("Registered client ${client.displayName}")
@@ -168,24 +169,18 @@ class NettyServerImpl : InitializingBean, DisposableBean {
168169
}
169170

170171
suspend fun unregisterClient(client: ServerClientImpl) {
171-
clientsLock.withLock {
172-
clients.remove(client)
173-
}
174-
172+
clients.invalidate(client.serverName)
175173
log.atInfo().log("Unregistered client ${client.displayName}")
176-
177174
serverManagerImpl.unregisterServer(client.serverId)
178175
}
179176

180177
suspend fun forEachClient(action: suspend (ServerClientImpl) -> Unit) {
181-
clientsLock.withLock {
182-
clients.forEach { action(it) }
178+
for (client in clients.asMap().values) {
179+
action(client)
183180
}
184181
}
185182

186183
suspend fun clientsSnapshot(): List<ServerClientImpl> {
187-
return clientsLock.withLock {
188-
clients.toList()
189-
}
184+
return clients.asMap().values.toObjectList()
190185
}
191186
}

0 commit comments

Comments
 (0)