11using ProjectVG . Application . Services . Session ;
2- using ProjectVG . Application . Services . WebSocket ;
32using ProjectVG . Infrastructure . Auth ;
43using ProjectVG . Infrastructure . Realtime . WebSocketConnection ;
4+ using ProjectVG . Domain . Services . Server ;
55using System . Net . WebSockets ;
66
77namespace ProjectVG . Api . Middleware
@@ -10,22 +10,25 @@ public class WebSocketMiddleware
1010 {
1111 private readonly RequestDelegate _next ;
1212 private readonly ILogger < WebSocketMiddleware > _logger ;
13- private readonly IWebSocketManager _webSocketService ;
14- private readonly IConnectionRegistry _connectionRegistry ;
13+ private readonly ISessionManager _sessionManager ;
14+ private readonly IWebSocketConnectionManager _connectionManager ;
1515 private readonly IJwtProvider _jwtProvider ;
16+ private readonly IServerRegistrationService ? _serverRegistrationService ;
1617
1718 public WebSocketMiddleware (
1819 RequestDelegate next ,
1920 ILogger < WebSocketMiddleware > logger ,
20- IWebSocketManager webSocketService ,
21- IConnectionRegistry connectionRegistry ,
22- IJwtProvider jwtProvider )
21+ ISessionManager sessionManager ,
22+ IWebSocketConnectionManager connectionManager ,
23+ IJwtProvider jwtProvider ,
24+ IServerRegistrationService ? serverRegistrationService = null )
2325 {
2426 _next = next ;
2527 _logger = logger ;
26- _webSocketService = webSocketService ;
27- _connectionRegistry = connectionRegistry ;
28+ _sessionManager = sessionManager ;
29+ _connectionManager = connectionManager ;
2830 _jwtProvider = jwtProvider ;
31+ _serverRegistrationService = serverRegistrationService ;
2932 }
3033
3134 public async Task InvokeAsync ( HttpContext context )
@@ -88,19 +91,59 @@ private string ExtractToken(HttpContext context)
8891 return string . Empty ;
8992 }
9093
91- /// <summary>
92- /// 기존 연결 정리 후 새 연결 등록
94+ /// <summary>
95+ /// 새 아키텍처: 세션 관리와 WebSocket 연결 관리 분리
9396 /// </summary>
9497 private async Task RegisterConnection ( Guid userId , WebSocket socket )
9598 {
96- if ( _connectionRegistry . TryGet ( userId . ToString ( ) , out var existing ) && existing != null ) {
97- _logger . LogInformation ( "기존 연결 정리: {UserId}" , userId ) ;
98- await _webSocketService . DisconnectAsync ( userId . ToString ( ) ) ;
99- }
99+ var userIdString = userId . ToString ( ) ;
100+ _logger . LogInformation ( "[WebSocketMiddleware] 연결 등록 시작: UserId={UserId}" , userId ) ;
101+
102+ try
103+ {
104+ // 기존 로컬 연결이 있으면 정리
105+ if ( _connectionManager . HasLocalConnection ( userIdString ) )
106+ {
107+ _logger . LogInformation ( "[WebSocketMiddleware] 기존 로컬 연결 발견 - 정리 중: UserId={UserId}" , userId ) ;
108+ _connectionManager . UnregisterConnection ( userIdString ) ;
109+ }
110+
111+ // 1. 세션 관리자에 세션 생성 (Redis 저장)
112+ await _sessionManager . CreateSessionAsync ( userId ) ;
113+ _logger . LogInformation ( "[WebSocketMiddleware] 세션 관리자에 세션 저장 완료: UserId={UserId}" , userId ) ;
114+
115+ // 2. WebSocket 연결 관리자에 로컬 연결 등록
116+ var connection = new WebSocketClientConnection ( userIdString , socket ) ;
117+ _connectionManager . RegisterConnection ( userIdString , connection ) ;
118+ _logger . LogInformation ( "[WebSocketMiddleware] 로컬 WebSocket 연결 등록 완료: UserId={UserId}" , userId ) ;
119+
120+ // 3. 분산 시스템: 사용자-서버 매핑 저장 (Redis)
121+ if ( _serverRegistrationService != null )
122+ {
123+ try
124+ {
125+ var serverId = _serverRegistrationService . GetServerId ( ) ;
126+ await _serverRegistrationService . SetUserServerAsync ( userIdString , serverId ) ;
127+ _logger . LogInformation ( "[WebSocketMiddleware] 사용자-서버 매핑 저장 완료: UserId={UserId}, ServerId={ServerId}" , userId , serverId ) ;
128+ }
129+ catch ( Exception mapEx )
130+ {
131+ _logger . LogWarning ( mapEx , "[WebSocketMiddleware] 사용자-서버 매핑 저장 실패: UserId={UserId}" , userId ) ;
132+ // 매핑 저장 실패는 로그만 남기고 연결은 계속 진행
133+ }
134+ }
100135
101- var connection = new WebSocketClientConnection ( userId . ToString ( ) , socket ) ;
102- _connectionRegistry . Register ( userId . ToString ( ) , connection ) ;
103- await _webSocketService . ConnectAsync ( userId . ToString ( ) ) ;
136+ // [디버그] 등록 후 상태 확인
137+ var isSessionActive = await _sessionManager . IsSessionActiveAsync ( userId ) ;
138+ var hasLocalConnection = _connectionManager . HasLocalConnection ( userIdString ) ;
139+ _logger . LogInformation ( "[WebSocketMiddleware] 연결 등록 완료: UserId={UserId}, SessionActive={SessionActive}, LocalConnection={LocalConnection}" ,
140+ userId , isSessionActive , hasLocalConnection ) ;
141+ }
142+ catch ( Exception ex )
143+ {
144+ _logger . LogError ( ex , "[WebSocketMiddleware] 연결 등록 실패: UserId={UserId}" , userId ) ;
145+ throw ;
146+ }
104147 }
105148
106149 /// <summary>
@@ -160,6 +203,17 @@ await socket.SendAsync(
160203 WebSocketMessageType . Text ,
161204 true ,
162205 cancellationTokenSource . Token ) ;
206+
207+ // 세션 하트비트 업데이트 (Redis TTL 갱신)
208+ try {
209+ if ( Guid . TryParse ( userId , out var userGuid ) )
210+ {
211+ await _sessionManager . UpdateSessionHeartbeatAsync ( userGuid ) ;
212+ }
213+ }
214+ catch ( Exception heartbeatEx ) {
215+ _logger . LogWarning ( heartbeatEx , "세션 하트비트 업데이트 실패: {UserId}" , userId ) ;
216+ }
163217 }
164218 }
165219 }
@@ -177,14 +231,39 @@ await socket.SendAsync(
177231 _logger . LogInformation ( "WebSocket 연결 해제: {UserId}" , userId ) ;
178232
179233 try {
180- await _webSocketService . DisconnectAsync ( userId ) ;
181- _connectionRegistry . Unregister ( userId ) ;
234+ // 새 아키텍처: 세션과 로컬 연결 분리해서 정리
235+ if ( Guid . TryParse ( userId , out var userGuid ) )
236+ {
237+ // 1. 세션 관리자에서 세션 삭제 (Redis에서 제거)
238+ await _sessionManager . DeleteSessionAsync ( userGuid ) ;
239+ _logger . LogDebug ( "세션 관리자에서 세션 삭제 완료: {UserId}" , userId ) ;
240+ }
241+
242+ // 2. 분산 시스템: 사용자-서버 매핑 제거 (Redis)
243+ if ( _serverRegistrationService != null )
244+ {
245+ try
246+ {
247+ await _serverRegistrationService . RemoveUserServerAsync ( userId ) ;
248+ _logger . LogDebug ( "사용자-서버 매핑 제거 완료: {UserId}" , userId ) ;
249+ }
250+ catch ( Exception mapEx )
251+ {
252+ _logger . LogWarning ( mapEx , "사용자-서버 매핑 제거 실패: {UserId}" , userId ) ;
253+ }
254+ }
255+
256+ // 3. 로컬 WebSocket 연결 해제
257+ _connectionManager . UnregisterConnection ( userId ) ;
258+ _logger . LogDebug ( "로컬 WebSocket 연결 해제 완료: {UserId}" , userId ) ;
182259
260+ // 4. WebSocket 소켓 정리
183261 if ( socket . State == WebSocketState . Open || socket . State == WebSocketState . CloseReceived ) {
184262 await socket . CloseAsync (
185263 WebSocketCloseStatus . NormalClosure ,
186264 "Connection closed" ,
187265 CancellationToken . None ) ;
266+ _logger . LogDebug ( "WebSocket 소켓 정리 완료: {UserId}" , userId ) ;
188267 }
189268 }
190269 catch ( Exception ex ) {
0 commit comments