Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine Signal R connection status without broadcasting Clients.All.someMethod() and blowing up client side resources

I'm concerned about using Clients.All in my C# Signal R hub class

Clients.All.setConnectionStatus(profileId, true);

I'm calling it in both OnConnected() and OnDisconnected(bool stopCalled) to show the online status of my logged in users. OnDisconnected() isn't as bad because it's only being called when someone actually logs off

ex.

public override Task OnConnected()
{
   string profileId = Context.User.Identity.Name;
   _connections.Add(profileId, Context.ConnectionId);
    Clients.All.setConnectionStatus(profileId, true);
    return base.OnConnected();
 }

public override Task OnDisconnected(bool stopCalled)
{
    string profileId = Context.User.Identity.Name;
    _connections.Remove(profileId, Context.ConnectionId);
    if (stopCalled == false) // log off only
        Clients.All.setConnectionStatus(profileId, false);
     return base.OnDisconnected(stopCalled);
}

My concern -> Blowing up the users machine client side with javascript code constantly running in the browser!

Scenario -> If I have > ~1000 users online and logged in traversing to different pages, I will be broadcasting to all of them a signal R connection Clients.All.setConnectionStatus(profileId, true);

which in the javascript hub looks like this below which could easily end up blowing up the users browser, because it would be constantly receiving these broadcasting connection status calls!!!

scope.chat = $.connection.chatHub;

// Receive and set the connection status
scope.chat.client.setConnectionStatus = function(profileId, isConnected) {
  // look for prfileId in html
  var $profileStatusElement = $(".online-status-profile[data-id='" + profileId + "']");
  var $profileChatElement = $(".online-status-chat[data-id='" + profileId + "']");
  
  if (isConnected === true) {
    // change the online status
  } else {
    // change the online status
  }
};

I have chat windows to users (online) like below that shows a users status next to their name. So I know if the person I'm sending a message to is online or not!

When I first load the chatbox, I fetch the online status server side, but after that it's up to the OnConnected() and OnDisconnected() methods in my hub to set the online status of the person I'm chatting with.

enter image description here

There's got to be a better way then broadcasting the signal out to 'all' online users on my site? But the only way I can think of is to poll the status every so often on some javascript timer, but I hate that idea!!

Another way would be to keep some kind of in-memory collection of who each person is chatting with, but that seems like it could get really messy and could end up up not being very accurate, being there could be so many things in between the client and server that could cause a disruption to mismanage the in-memory collection of who's connected to whom! Any thoughts or ideas here would be greatly appreciated!!

FYI -> I also have a messages page, that shows a list of all the recent conversations I've had with users like below. And on this page I show the online status of these users as well. On this page I fetch the online status of each user on the server before I render the page, same as the chat box, but once the page is loaded, it's up to the OnConnected() and OnDisconnected(bool stopCalled) to set the online status of each user on the page.

enter image description here

like image 252
user1186050 Avatar asked Oct 17 '22 10:10

user1186050


1 Answers

You're doing in right way with signalR. I guide you based on your concerns/scenarios:

My concern -> Blowing up the users machine client side with javascript code constantly running in the browser!

Don't forget that you are using a browser underlying functionality (WebSocket), so we have no choice unless running some js code inside client loaded page. You take advantage of browser capabilities here.

Scenario -> If I have > ~1000 users online and logged in traversing to different pages, I will be broadcasting to all of them a signal R connection Clients.All.setConnectionStatus(profileId, true);

Before proposing any solution, I exhort you to employ grouping logic in your application. Grouping reduces the volume of synchronizations.

If you working on a public chat room (which can contain large number of people), by employing server side strategies simply you'll make your code to a dirty one! Yes, Any user who navigates or refreshes the page can cause a redundant update to all the clients. Best Solution is turning you page to SPA (working with API call or Ajax call) with no page refresh. I believe that any real-time web application should take advantage of modern web technologies. This will solve almost every problem which you suffer (e.g no page refresh, no reRun, no disCoennection & etc ...).

Solutions like using a js timer to fetch latest status for users is not clean or desirable.

like image 96
Amirhossein Mehrvarzi Avatar answered Nov 13 '22 15:11

Amirhossein Mehrvarzi