SignalR - storing client information - signalr

I've started experimenting with SignalR. I've been trying to come up with a flexible way of storing information about each connected client. For example, storing the name in a chat app rather than passing it with each message.
At the moment, I have a static dictionary which matches the connectionId to an object which contains these properties. I add to this dictionary on connection, and remove on disconnection.
The issue I'm having is that I don't seem to get all disconnect events. If I close a tab in Chrome, the disconnect seems to go through. However, if I rapidly reload a tab, the disconnect doesn't seem to occur (at least not 'cleanly'). For example, if I reload the same tab over and over, it'll tell me my dictionary has multiple items when it should - in theory still be one.
Is there a standard way of storing this kind of per-connection information? Otherwise, what might be causing the issue I'm having?

You are actually handling connection id data correctly. Ensure that you are only instantiating your user data in OnConnected and uninstantiating it in OnDisconnected.
When spamming refresh on your page there are situations which result in the OnDisconnected event not being triggered immediately. However you should not worry about this because SignalR will actually time-out the connection and trigger the OnDisconnected event after a designated timeout (DisconnectTimeout).
If you do come across scenarios where there is not a 1-to-1 correlation for OnConnected and OnDisconnected events (after a significant amount of time) make sure to file a bug at https://github.com/SignalR/SignalR/issues.
Lastly if you're looking at doing some advanced chat mechanics and looking for some inspiration check out JabbR, it's open source!
https://github.com/davidfowl/JabbR
Hope this helps!

Related

How to handle client view synchronization with signal r when a client gets offline for a short period of time and some messages are lost?

I am using SignalR in my web api to provide real-time functionality to my client apps (mobile and web). Everything works ok but there is something that worries me a bit:
The clients get updated when different things happen in the backend. For example, when one of the clients does a CRUD operation on a resource that will be notified by SignalR. But, what happens when something happens on the client, let's say the mobile app, and the device data connection is dropped?.
It could happen that another client has done any action over a resource and when SignalR broadcasts the message it doesn't arrive to that client. So, that client will have an old view sate.
As I have read, it seems that there's no way to know if a meesage has been sent and received ok by all the clients. So, beside checking the network state and doing a full reload of the resource list when this happens is there any way to be sure message synchronization has been accomplished correctly on all the clients?
As you've suggested, ASP NET Core SignalR places the responsibility on the application for managing message buffering if that's required.
If an eventually consistent view is an issue (because order of operations is important, for example) and the full reload proves to be an expensive operation, you could manage some persistent queue of message events as far back as it makes sense to do so (until a full reload would be preferable) and take a page from message buses and event sourcing, with an onus on the client in a "dumb broker/smart consumer"-style approach.
It's not an exact match of your case, but credit where credit is due, there's a well thought out example of handling queuing up SignalR events here: https://stackoverflow.com/a/56984518/13374279 You'd have to adapt that some and give a numerical order to the queued events.
The initial state load and any subsequent events could have an aggregate version attached to them; at any time that the client receives an event from SignalR, it can compare its currently known state against what was received and determine whether it has missed events, be it from a disconnection or a delay in the hub connection starting up after the initial fetch; if the client's version is out of date and within the depth of your queue, you can issue a request to the server to replay the events out to that connection to bring the client back up to sync.
Some reading into immediate consistency vs eventual consistency may be helpful to come up with a plan. Hope this helps!

Meteor.userId lost on server changes dev reload

I'm building a somewhat big application. When changing code the server restart and force refresh on the client.
The client keep his session data, but I seem to lose the Meteor.Collection previously sync data, forcing my user to re-sync everything.
I use 0.5.7(did not see anything in 0.5.8 about that)
Is that the expected behavior or I'm I missing something?
This can be tested by adding something like that at your client start (Assuming Components is your Meteor.Collection)
console.log("Length: ", Components.find().fetch().length);
No, you're not missing anything. The collection data should be re-synced on code pushes. However, if your collection data takes more than a second or two to load in, you should look into trying to send less data to the client by creating finer-grained subscriptions that only send data the client needs at the moment.

SignalR Disconections

I am using Signalr in an application I'm writing and storing all the user connections in a concurrent dictionary
ConcurrentDictionary<string, User> _users = new ConcurrentDictionary<string, User>();
e.g.
https://github.com/SignalR/SignalR/blob/master/samples/SignalR.Hosting.AspNet.Samples/Hubs/ShapeShare/ShapeShare.cs
I have implemented the IDisconnect interface on my Hub and I'm removing users from the dictionary when they disconnect
I am wondering how reliable the Disconnect method really is?
Does it capture all the different ways that a user could diconnect?
I dont want the dictionary to grow and grow indefinitely
I was thinking of maybe having a timer to periodically traverse the dictionary and remove users who havent had any recent activity
Is this necessary? Can I rely on the disconnect method?
Check out https://github.com/SignalR/SignalR/wiki/Configuring-SignalR , there are settings for :
DisconnectTimeout
KeepAlive
& Heatbeat interval
These could all be applied to help in maintaining your dictionary.
In my experience a graceful disconnect seems to work perfectly on signalR (still problems with win-apps) , if it ungracefully disconnects in a few minutes the connection will timeout and the disconnect method will fire and remove it from your dictionary like Drew said.
You could create a method that sends a message to all clients and log the returned connection ID and then remove any entries that are old, but in practice the disconnect method does work/work itself out, I would only implement the heartbeat interval if you really need to keep a very close eye on the connections.
If it doesn't fire it's a bug and you should report an issue to the SignalR project on GitHub. Here's a list of open issues with Disconnects at this time.
Be aware that diff. transports have diff. disconnect detection logic and so, depending on which transport the user is using, you will see diff. patterns of when the Disconnect fires, but it SHOULD fire eventually for all transports.

How to dynamically keep track on button click count on ASP .NET

I want to make a form where people can sign up for a course. Number of people for a course is limited. I want to make a page where user can see how many places are still available and that number is dynamically updated, so if another user signs for a course the other one sees change. When number of available places reaches 0 the signup button should be disabled. Such task should be easy to implement but I am afraid it is not. I suppose some Ajax will be involved but how to handle server side counting? WebServices? I have a problem to design a logic behind all of this.
The technology/technique you're looking for is called Server Push.
Basic idea: Client should respond to some events happening on Server.
Possible solutions:
Polling some server action via AJAX in a timely fashion;
Keeping long-running AJAX request open on server-side until timeout occurs or event happens, then process acquired result on client (determine if it was server action or just timeout), reestablish connection from client if necessary.
and a couple of other solutions which are basically variations of the above two. Also solution will much depend on server-side technology you're using.
Google has a short yet very informative article on what this technique is and how it can be implemented here. It's (almost) technology agnostic so it should help you to understand concepts and possible solutions.
I'd use a database on the server. For the "courses" table, have an associated table containing the "bookings". Add them up in a SQL query.

How to 'subscribe' to an event that ripples to client

I know that there are a variety of similarly posed questions here on SO and I've had a look at the ones that are suggested as matches. However, none quite manage to solve the issue that I'm facing. Basically, I'd like to know if there's a way to 'subscribe' to an event at client level in order to have a small portion of the page rendered from the controller. I know that I can use javascript setInterval() (in combination with jquery ajax) to 'poll' the controller action in order to determine if something 'new' should be renedered onto the page. However, I'm not a huge fan of polling, especially when client browsers can be left unattended and are uneccessarily polling for changes. Multiply that by the number of potential client machines that could be browsing the app and you get a feel for the scale of the issue with this approach. Now, in truth, this is EXACTLY the approach that I use to refresh certain page fragments on some ('read' - MANY!!) of my existing sites.
However, I'd like to know what the options are for subscribing in 'reverse' to events and having the controller 'know' about the client browser and any events that it is subscribed to and the controller then 'push' out the update to the client on a 'needs must' basis. Is this something that happens outside of the normal desktop events scenario?? is the idea even scaleable or is it just the same potential bottleneck in reverse of the method that I currently use.
Hopefully, some interesting approaches out there to this double edged sword.
The server can not contact the client. The only other option besides polling is leaving an open connection between the client and server that the server can then stream info through. This is not less resource consuming than polling.
You can write a script that detects action on the client browser and goes into a "sleep" mode after a few idle minutes during which it does not poll.
Never tried it, as it seems to me that maintaining a long-running connection is a good way to run out of worker threads1 - but Comet seems to be what you're looking for.
Note that others have suggested ways around the thread per connection model.

Resources