|
4 | 4 | using ProjectVG.Domain.Services.Server; |
5 | 5 | using ProjectVG.Application.Services.Session; |
6 | 6 | using StackExchange.Redis; |
| 7 | +using System.Collections.Concurrent; |
7 | 8 |
|
8 | 9 | namespace ProjectVG.Application.Services.MessageBroker |
9 | 10 | { |
@@ -200,16 +201,15 @@ private async void OnUserMessageReceived(RedisChannel channel, RedisValue messag |
200 | 201 | _logger.LogInformation("[분산브로커] 메시지 파싱 완료: TargetUserId={TargetUserId}, SourceServerId={SourceServerId}, MessageType={MessageType}", |
201 | 202 | brokerMessage.TargetUserId, brokerMessage.SourceServerId, brokerMessage.MessageType); |
202 | 203 |
|
203 | | - // 로컬에서 해당 사용자가 연결되어 있는지 확인 |
204 | | - var isLocalActive = _connectionRegistry.IsConnected(brokerMessage.TargetUserId); |
205 | | - _logger.LogInformation("[분산브로커] 로컬 세션 확인: TargetUserId={TargetUserId}, IsLocalActive={IsLocalActive}", |
206 | | - brokerMessage.TargetUserId, isLocalActive); |
207 | | - |
208 | | - if (isLocalActive) |
| 204 | + if (_connectionRegistry.TryGet(brokerMessage.TargetUserId, out var connection) && connection != null) |
209 | 205 | { |
210 | | - var payload = brokerMessage.DeserializePayload<object>(); |
211 | | - await SendLocalMessage(brokerMessage.TargetUserId, payload); |
212 | | - |
| 206 | + var payloadText = brokerMessage.Payload; |
| 207 | + if (string.IsNullOrEmpty(payloadText)) |
| 208 | + { |
| 209 | + _logger.LogWarning("[분산브로커] 빈 Payload 수신: Channel={Channel}, TargetUserId={TargetUserId}", channel, brokerMessage.TargetUserId); |
| 210 | + return; |
| 211 | + } |
| 212 | + await connection.SendTextAsync(payloadText); |
213 | 213 | _logger.LogInformation("[분산브로커] 분산 사용자 메시지 처리 완료: TargetUserId={TargetUserId}", brokerMessage.TargetUserId); |
214 | 214 | } |
215 | 215 | else |
@@ -257,9 +257,45 @@ private async void OnBroadcastMessageReceived(RedisChannel channel, RedisValue m |
257 | 257 | return; |
258 | 258 | } |
259 | 259 |
|
| 260 | + _logger.LogDebug("브로드캐스트 메시지 수신: {MessageType}, SourceServer: {SourceServerId}", |
| 261 | + brokerMessage.MessageType, brokerMessage.SourceServerId); |
| 262 | + |
260 | 263 | // 현재 서버에 연결된 모든 사용자에게 브로드캐스트 |
261 | | - // TODO: IConnectionRegistry에서 모든 활성 사용자 목록을 가져와서 전송 |
262 | | - _logger.LogDebug("브로드캐스트 메시지 수신: {MessageType}", brokerMessage.MessageType); |
| 264 | + var activeConnections = _connectionRegistry.GetAllActiveConnections().ToList(); |
| 265 | + if (activeConnections.Count == 0) |
| 266 | + { |
| 267 | + _logger.LogDebug("브로드캐스트 대상 없음: 활성 연결 수 = 0"); |
| 268 | + return; |
| 269 | + } |
| 270 | + |
| 271 | + var broadcastTasks = new List<Task>(); |
| 272 | + var successCount = 0; |
| 273 | + var failureCount = 0; |
| 274 | + |
| 275 | + foreach (var (userId, connection) in activeConnections) |
| 276 | + { |
| 277 | + var task = Task.Run(async () => |
| 278 | + { |
| 279 | + try |
| 280 | + { |
| 281 | + await connection.SendTextAsync(brokerMessage.Payload); |
| 282 | + Interlocked.Increment(ref successCount); |
| 283 | + _logger.LogTrace("브로드캐스트 전송 성공: UserId={UserId}", userId); |
| 284 | + } |
| 285 | + catch (Exception ex) |
| 286 | + { |
| 287 | + Interlocked.Increment(ref failureCount); |
| 288 | + _logger.LogWarning(ex, "브로드캐스트 전송 실패: UserId={UserId}", userId); |
| 289 | + } |
| 290 | + }); |
| 291 | + broadcastTasks.Add(task); |
| 292 | + } |
| 293 | + |
| 294 | + // 모든 전송 완료 대기 (타임아웃 5초) |
| 295 | + await Task.WhenAll(broadcastTasks).ConfigureAwait(false); |
| 296 | + |
| 297 | + _logger.LogInformation("브로드캐스트 완료: 대상={TotalCount}, 성공={SuccessCount}, 실패={FailureCount}", |
| 298 | + activeConnections.Count, successCount, failureCount); |
263 | 299 | } |
264 | 300 | catch (Exception ex) |
265 | 301 | { |
|
0 commit comments