| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- using Application.Abstractions.Cache;
- using Application.Abstractions.Chat;
- using StackExchange.Redis;
- using System.Text.Json;
- namespace Infrastructure.Chat;
- public class RedisChatConnectionTracker(IConnectionMultiplexer redis) : IChatConnectionTracker
- {
- private readonly IDatabase _db = redis.GetDatabase();
- private static readonly JsonSerializerOptions _jsonOptions = new()
- {
- PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
- WriteIndented = false
- };
- public async Task AddAsync(string roomKey, ConnectedUser user)
- {
- var json = JsonSerializer.Serialize(user, _jsonOptions);
- await _db.HashSetAsync(CacheKeys.ChatRoomConnections(roomKey), user.ConnectionId, json);
- }
- public async Task RemoveAsync(string roomKey, string connectionId)
- {
- await _db.HashDeleteAsync(CacheKeys.ChatRoomConnections(roomKey), connectionId);
- }
- public async Task<IReadOnlyList<ConnectedUser>> GetByRoomAsync(string roomKey)
- {
- var entries = await _db.HashGetAllAsync(CacheKeys.ChatRoomConnections(roomKey));
- if (entries.Length <= 0)
- {
- return [];
- }
- var list = new List<ConnectedUser>(entries.Length);
- foreach (var entry in entries)
- {
- if (!entry.Value.IsNullOrEmpty)
- {
- var user = JsonSerializer.Deserialize<ConnectedUser>((string)entry.Value!, _jsonOptions);
- if (user is not null)
- {
- list.Add(user);
- }
- }
- }
- return list.AsReadOnly();
- }
- public async Task<int> GetCountByRoomAsync(string roomKey)
- {
- return (int)await _db.HashLengthAsync(CacheKeys.ChatRoomConnections(roomKey));
- }
- public async Task<IReadOnlyList<(
- string RoomKey,
- ConnectedUser User
- )>> GetAllAsync()
- {
- // 모든 룸 키를 스캔 후 병합 (관리자 집계용)
- var server = _db.Multiplexer.GetServer(_db.Multiplexer.GetEndPoints().First());
- var list = new List<(
- string RoomKey,
- ConnectedUser User
- )>();
- await foreach (var key in server.KeysAsync(pattern: "chat:room:*:connections"))
- {
- // 키에서 roomKey 추출 — chat:room:{key}:connections
- var keyStr = (string)key!;
- var roomKey = keyStr["chat:room:".Length..^":connections".Length];
- var entries = await _db.HashGetAllAsync(key);
- foreach (var entry in entries)
- {
- if (!entry.Value.IsNullOrEmpty)
- {
- var user = JsonSerializer.Deserialize<ConnectedUser>((string)entry.Value!, _jsonOptions);
- if (user is not null)
- {
- list.Add((roomKey, user));
- }
- }
- }
- }
- return list.AsReadOnly();
- }
- public async Task ClearAllAsync()
- {
- // 서버 시작 시 모든 룸 연결 초기화 (stale 제거)
- var server = _db.Multiplexer.GetServer(_db.Multiplexer.GetEndPoints().First());
- await foreach (var key in server.KeysAsync(pattern: "chat:room:*:connections"))
- {
- await _db.KeyDeleteAsync(key);
- }
- // 구 채널 키 체계(chat:channel:*) 잔재 정리 — roomKey 전환 이전 배포분 호환
- await foreach (var key in server.KeysAsync(pattern: "chat:channel:*:connections"))
- {
- await _db.KeyDeleteAsync(key);
- }
- }
- }
|