Does Signalr change connectionId OnReconnected method? - signalr

I was wondering if signalr changes the connectionId on OnReconnected method? as I'm mapping a list of users to their connection ids so if the reconneced event raised on the server due to slow connection for example will the connectionId will be changed ?

No. The connectionId does not change in an OnReconnected event.
The OnReconnected fires automatically(if you're using a signalR client) within the disconnect timeout in case there is a network issue and a keep alive is missed.
If the network is disrupted or the server is unable to process the OnReconnected event for longer than the disconnect timeout, the connection will be disconnected on the server and a new connection will need to be made. This making a new connection is not automatic. The client code will have to call a connection.Start() to create a new connection.
If the client comes back with the old connectionId, it will not go through as that connection would be in a disconnected state.
So if you are mapping connectionIDs with Users then you need to make sure that the connection Id is updated with the new connectionId in every OnConnected event and deleted in every OnDisconnected event on the server .

I don't believe the OnReconnect will change the connectionID. However, that depends on what the cause of the problem is.
If the client dropped it's internet connection for example and then picked back up, OnReconnect fires and the user should have the same connectionID.
If the server rebooted or IIS restarted, then you have a different situation and when your clients refresh it will appear as a OnConnect and get a new connectionID.

Related

Meteor - Way for server side to tell if a user has left the website?

Since Meteor uses WebSockets, I'm guessing it might be easy to tell if a user has actually closed their browser or at least the tab with a Meteor website in it. Is this doable, and if so, how?
From the Meteor Docs: Meteor.onConnection:
Meteor.onConnection(callback) Server
onConnection returns an object with a single method stop. Calling stop unregisters the callback, so that this callback will no longer be called on new connections.
The callback is called with a single argument, the server-side connection representing the connection from the client.
The server-side connection object has the onClose field:
onClose Function
Register a callback to be called when the connection is closed. If the connection is already closed, the callback will be called immediately.
Important to note is that this callback will call every time the connection drops. Whether the user closes their browser, or has just temporarily lost their connection and will be back shortly.

Exception when sending message to disconnected client in SignalR

In a Hub, I am sending a message to a client using
try {
GlobalHost.ConnectionManager.GetHubContext<ContextManagerHub>().Clients.Client(connectionID).SendMessage(message);
} catch(Exception ex) {
HandleError(ex);
}
The connectionId is stored using OnConnected and removed using OnDisconnected on the Hub.
I am a little worried that I am sending messages to disconnected clients, and would like to get exceptions if I do. But the code above never raises exception, even if I try using connectionID = "BAD_ID". Anyone got an idea on how to figure out if the SendMessage actually fails?
So SignalR does not actually validate if your sending to an invalid ConnectionId. The reason why this does not occur is because ConnectionId's for clients are a lot like SignalR groups. They reference a topic that can be subscribed and published to.
Therefore when sending to an invalid ConnectionId you push a message to a topic that doesn't exist yet; so it's created. The reasoning behind this is if a client happens to come to the server with that connection id via a reconnect or by other means they will then receive any messages that they had missed during their down time.
Sooo for your case I'd recommend tracking clients via the OnConnected and OnDisconnected methods and then running logic to verify that they are present prior to sending to them.

Reusing same connection in signalR while navigating through different pages

I have an MVC project, with multiple pages.
I have a long running process, which updates the client on its progress. However, this update is sent only to a single client, instead of broadcasting to all.
Clients.Client(ConnectionId).sendMessage(msg);
In my layout.cshtml, this is how I connect to the hub
var serverHub = $.connection.notifier;
window.hubReady = $.connection.hub.start(function () { });
The problem is, when I navigate to another page, I no longer receive the messages from signalr, because the connection id has changed.
How should I workaround this issue, such that my signalr hub can still send messages to a single client, while the client navigates from page to page.
You will want to create a server mapping of users to connection id's. See: SignalR 1.0 beta connection factory.
You will want to let your users persist past an OnDisconnected event and when they connect with a different connection Id you can continue pumping data down to them.
So the thought process could be as follows:
Page loads, SignalR connection is instantiated
Once connection is fully started call => TryCreateUser (returns a user, whether it existed or it was created).
Long Running process Starts
Client changes pages -> SignalR connection stops
New Page loads, new SignalR connection is instantiated
Once connection is fully started see if you have a cookie, session, or some type of data representing who you are => TryCreateUser(userData) (returns the user you created on the last page).
Data continues pumping down to user.
Note: if you take an authentication approach you will have to be authenticated prior to starting a connection and that data cannot change during the lifetime of a SignalR connection, it can only be created/modified while the connection is in the disconnected state.

Maintaining an open Redis PubSub subscription with Booksleeve

I am using a Redis pubsub channel to send messages from a pool of worker processes to my ASP.NET application. When a message is received, my application forwards the message to a client's browser with SignalR.
I found this solution to maintaining an open connection to Redis, but it doesn't account for subscriptions when it recreates the connection.
I'm currently handling Redis pubsub messages in my Global.asax file:
public class Application : HttpApplication
{
protected void Application_Start()
{
var gateway = Resolve<RedisConnectionGateway>();
var connection = gateway.GetConnection();
var channel = connection.GetOpenSubscriberChannel();
channel.PatternSubscribe("workers:job-done:*", OnExecutionCompleted);
}
/// <summary>
/// Handle messages received from workers through Redis.</summary>
private static void OnExecutionCompleted(string key, byte[] message)
{
/* forwarded the response to the client that requested it */
}
}
The problem occurs when the current RedisConnection is closed for whatever reason. The simplest solution the problem would be to fire an event from the RedisConnectionGateway class when the connection has been reset, and resubscribe using a new RedisSubscriberChannel. However, any messages published to the channel while the connection is being reset would be lost.
Are there any examples of recommended ways to handle this situation?
Yes, if the connection dies (network instability, re-mastering, whatever) then you will need to re-apply any subscriptions you have made. An event to reconnect and resubscribe is pretty normal, and not very different to what we use here on SE/SO (except we typically track more granular subscriptions, and have some wrapper code that handles all that).
Yes, any events published while your connection was broken are gone. That is the nature of redis pub/sub; it does not guarantee delivery to disconnected clients. Either use a tool that does promise this, or use redis to drive a queue instead - pushing/popping to/from opposite ends of a list is usually a reasonable alternative, and ensures nothing is lost (as long as your software doesn't drop it after popping it from the list). If it helps, I have on my list a request to add the blocking pop methods - they totally destroy the multiplexer intent, but they have genuine use in some cases, so I'm not against adding them.

blazeds how to understand if the session is timed out

Hi my aim is to catch when the session is invalidated and send message to all destination that the FlexClient subscribed that the client wiht id .... has disconnected.
I implemented a service which listens for sessionCretaed,sessionDestroyed,clientCreated,clientDestroyed,messageClientCreated,messageClientDestroyed.
Problem is that i want to catch messageClientDestroyed and send to that destination a message that the user has disconnected.But blazeds destroys messageClient when you add a subtopic.So how to understand that if session is invalidated and all messageClient are being destroyed or the user just enter another place and add a subtopic to his consumer.
I'am also open for other solutions to implement that mechanism.When user disconnected by session timeout or closed the site browser etc. i wanna catch it and send a message to subscribed destinations.
thank you.
I am not a master on this topic but I believe you have to tune into the Flex session lifecycle event, FlexSessionListener after a d/c.
If your client is leaving because they want to, on the flex side you invoke disconnectAll() on the ChanelSet so that Blaze DS will clean up resources explicitly.
If your client is leaving because of timing out, you can configure the channel definition to use invalidate-session-on-disconnect = true
These two should trigger the FlexSessionListner.sessionDestroyed(). The parameter for this method is a FlexSession object where you can extrapolate what you need.

Resources