feat(user-creator-chat): WebSocket 세션 레지스트리를 추가한다
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package kr.co.vividnext.sodalive.v2.usercreatorchat.websocket
|
||||
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.socket.WebSocketSession
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@Component
|
||||
class UserCreatorChatWebSocketSessionRegistry {
|
||||
private val sessionsByRoomMember = ConcurrentHashMap<RoomMemberKey, ConcurrentHashMap<String, WebSocketSession>>()
|
||||
private val sessionIndexes = ConcurrentHashMap<String, RoomMemberKey>()
|
||||
private val lockStripes = Array(LOCK_STRIPE_COUNT) { Any() }
|
||||
|
||||
fun register(roomId: Long, memberId: Long, session: WebSocketSession) {
|
||||
val sessionId = session.id
|
||||
synchronized(lockFor(sessionId)) {
|
||||
removeLocked(sessionId)
|
||||
|
||||
val key = RoomMemberKey(roomId, memberId)
|
||||
sessionsByRoomMember.computeIfAbsent(key) { ConcurrentHashMap() }[sessionId] = session
|
||||
sessionIndexes[sessionId] = key
|
||||
}
|
||||
}
|
||||
|
||||
fun findSessions(roomId: Long, memberId: Long): List<WebSocketSession> {
|
||||
return sessionsByRoomMember[RoomMemberKey(roomId, memberId)]?.values?.toList() ?: emptyList()
|
||||
}
|
||||
|
||||
fun remove(sessionId: String) {
|
||||
synchronized(lockFor(sessionId)) {
|
||||
removeLocked(sessionId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeLocked(sessionId: String) {
|
||||
val key = sessionIndexes.remove(sessionId) ?: return
|
||||
val sessions = sessionsByRoomMember[key] ?: return
|
||||
sessions.remove(sessionId)
|
||||
if (sessions.isEmpty()) {
|
||||
sessionsByRoomMember.remove(key, sessions)
|
||||
}
|
||||
}
|
||||
|
||||
private fun lockFor(sessionId: String): Any {
|
||||
return lockStripes[Math.floorMod(sessionId.hashCode(), lockStripes.size)]
|
||||
}
|
||||
|
||||
private data class RoomMemberKey(
|
||||
val roomId: Long,
|
||||
val memberId: Long
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val LOCK_STRIPE_COUNT = 64
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user