From bdbd00bb2ad6541f7a6b2a21b6816bda40960260 Mon Sep 17 00:00:00 2001 From: AlanMoonbase Date: Sat, 12 Jul 2025 10:50:36 -0700 Subject: [PATCH] Rework Online User Tracking --- qtc-net-server/Hubs/ChatHub.cs | 97 +++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 31 deletions(-) diff --git a/qtc-net-server/Hubs/ChatHub.cs b/qtc-net-server/Hubs/ChatHub.cs index e167928..5f9b81c 100644 --- a/qtc-net-server/Hubs/ChatHub.cs +++ b/qtc-net-server/Hubs/ChatHub.cs @@ -8,10 +8,10 @@ namespace qtc_api.Hubs private IUserService _userService; private IRoomService _roomService; private ILogger _logger; - private static List ConnectedUsers = new(); - private static List OnlineUsers = new(); - private static Dictionary> GroupUsers = new(); + private static readonly Dictionary> GroupUsers = []; + private static readonly Dictionary> ConnectedUsers = []; + private static readonly List OnlineUsers = []; public ChatHub(IUserService userService, IRoomService roomService, ILogger logger) { @@ -20,25 +20,6 @@ namespace qtc_api.Hubs _logger = logger; } - public override async Task OnDisconnectedAsync(Exception? ex) - { - Log("Client Disconnected From Hub"); - - var connection = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId); - - if (connection != null) - { - var user = OnlineUsers.FirstOrDefault(x => x.Id == connection.ConnectedUser!.Id); - - if (user != null) - { - ConnectedUsers.Remove(connection); - OnlineUsers.Remove(user); - await LogoutAsync(user); - } - } - } - public async override Task OnConnectedAsync() { Log("Client Connected To Hub"); @@ -49,10 +30,61 @@ namespace qtc_api.Hubs var user = await _userService.GetUserById(uid); if (user != null && user.Success && user.Data != null) { - // log them in - ConnectedUsers.Add(new UserConnectionDto() { ConnectedUser = user.Data, ConnectionId = Context.ConnectionId }); - OnlineUsers.Add(user.Data); - await LoginAsync(user.Data); + var userId = user.Data.Id; + + lock (ConnectedUsers) + { + if(!ConnectedUsers.TryGetValue(userId, out List? value)) + { + value = []; + ConnectedUsers[userId] = value; + } + + value.Add(Context.ConnectionId); + } + + if(!OnlineUsers.Any(e => e.Id == userId)) + { + OnlineUsers.Add(user.Data); + await LoginAsync(user.Data); + } + } + } + } + + public override async Task OnDisconnectedAsync(Exception? ex) + { + Log("Client Disconnected From Hub"); + + var uid = Context.UserIdentifier; + if (uid != null) + { + var user = await _userService.GetUserById(uid); + if (user != null && user.Success && user.Data != null) + { + var userId = user.Data.Id; + + lock (ConnectedUsers) + { + if(ConnectedUsers.TryGetValue(userId, out List? value)) + { + value.Remove(Context.ConnectionId); + } + } + + if (ConnectedUsers[userId].Count == 0) + { + ConnectedUsers.Remove(userId); + if (OnlineUsers.Any(e => e.Id == userId)) + { + var onlineUser = OnlineUsers.FirstOrDefault(e => e.Id == userId); + if(onlineUser != null) + { + OnlineUsers.Remove(onlineUser); + await LogoutAsync(onlineUser); + } + } + } } } } @@ -155,12 +187,15 @@ namespace qtc_api.Hubs public async Task SendDirectMessageAsync(User user, UserInformationDto userToMsg, Message message) { // send direct message directly to connected user - var connection = ConnectedUsers.FirstOrDefault(e => e.ConnectedUser.Id == userToMsg.Id); - if (connection != null) + if(ConnectedUsers.TryGetValue(userToMsg.Id, out List? value)) { - UserInformationDto userInformationDto = new UserInformationDto { Id = user.Id, Username = user.Username, Bio = user.Bio, Role = user.Role, Status = user.Status, CreatedAt = user.CreatedAt, DateOfBirth = user.DateOfBirth, ProfilePicture = user.ProfilePicture }; - await Clients.Client(connection.ConnectionId).SendAsync("ReceiveDirectMessage", message, userInformationDto); - return; + var connection = value.FirstOrDefault(); + if(connection != null) + { + UserInformationDto userInformationDto = new UserInformationDto { Id = user.Id, Username = user.Username, Bio = user.Bio, Role = user.Role, Status = user.Status, CreatedAt = user.CreatedAt, DateOfBirth = user.DateOfBirth, ProfilePicture = user.ProfilePicture }; + await Clients.Client(connection).SendAsync("ReceiveDirectMessage", message, userInformationDto); + return; + } } }