using System.Collections.Concurrent; namespace RelayServer.Services.Chat; public static class ConnectedClientService { private static readonly ConcurrentDictionary SessionToUsername = new(); private static readonly ConcurrentDictionary> UsernameToSessions = new(StringComparer.OrdinalIgnoreCase); public static void Register(string sessionId, string username) { if (SessionToUsername.TryGetValue(sessionId, out var oldUsername) && !string.Equals(oldUsername, username, StringComparison.OrdinalIgnoreCase)) { RemoveSessionFromUsername(sessionId, oldUsername); } SessionToUsername[sessionId] = username; var sessions = UsernameToSessions.GetOrAdd(username, _ => new HashSet(StringComparer.Ordinal)); lock (sessions) sessions.Add(sessionId); } public static void Unregister(string sessionId) { if (SessionToUsername.TryRemove(sessionId, out var username)) RemoveSessionFromUsername(sessionId, username); } public static IReadOnlyCollection GetSessionsForUser(string username) { if (UsernameToSessions.TryGetValue(username, out var sessions)) lock (sessions) return sessions.ToList(); return Array.Empty(); } public static string? GetUsernameForSession(string sessionId) => SessionToUsername.TryGetValue(sessionId, out var u) ? u : null; private static void RemoveSessionFromUsername(string sessionId, string username) { if (!UsernameToSessions.TryGetValue(username, out var sessions)) return; lock (sessions) { sessions.Remove(sessionId); if (sessions.Count == 0) UsernameToSessions.TryRemove(username, out _); } } }