Reliable timer for a chat room - javascript

Please help to choose a solution (nodeJS + socket.io + redis) for a chat room timer.
Multiple Rooms are created, every room has exactly one HOST i.e admin for that room, every room will have 500 members in it. There can be 'n' rooms at any time 't'. A room will be destroyed after 1 hour of creation.
Node server => Process room's member related data from redis and broadcast it in every room after some interval. this interval (i.e When to broadcast) is decided by an array, call it as timerArrayForRoom1. This array holds the time in seconds when to broadcast data. This array is different for every room.
Now, two approaches -
Using setInterval() in nodeJS so that it will call its broadcasting method after some time interval. Every room will have its separate interval object.
Give timerArrayForRoom1 to the HOST of the room and let the host fire an event after some seconds as per the timer array. i.e using setinterval() on client side. And node server will take its action on that event.
First approach is HOST independent but it involves use of setInterval() in NodeJS.
Which one would be better to implement so that server will be able to support 1000 rooms having 500 members in it running and broadcasting all at a time ?
Which is more reliable? (as I read setInterval() does not guarantee its time to call the function)
Or any other approach?
Host/admin will be different device and exactly one for every room, so second approach will balance the server load to some extent.

setInterval from your node server is the way to go. You already give a good reason that it is independant of the clients. Also while it may not guarantee its time to execute. It is the closest to execute ontime.
This should work reasonably accurate unless your server hangs up because of CPU intensive execution. Also allowing HOST or any other client to initiate event is susceptible to same drawbacks.

Related

Synchronizing Socket.IO calls across multiple clients

I'm pretty new to Javascript, Node, socket.io, and multiplayer game development in general, so I apologize in advance for anything obvious that I missed.
I have a node.js server that, when a browser goes to a particular website, creates a socket.io connection with that user. The server-side code receives any messages from a player and forwards it to whatever other players need that message
I'm trying to synchronize function calls across different browsers, so that they're called at as close to the same time as possible.
The expected workflow:
Player 1 sends a message that commands players 2 and 3 to run a function at the same time (in this case, a Countdown) as soon as possible
The server receives the message and sends it to Players 2 and 3
Players 2 and 3 both receive the message and start the countdown at the same time (or as close to the same time as possible)
Is there a standard way to synchronize calls like this across different socket connections?

Handling timers for many users in Nodejs

I'm building a web app in Node/Express such that users can set a timer so that a certain task gets executed or repeated. My question is how can I set timer for many users with an event triggered after deadline. I don't want to handle this on the client side beacuse users can close the browser. A good example of this is services such as pingdom.com that allow you to set timer and send a ping every X minutes to your server. How can this be acheived?
I hope I don't get many negatives for asking this and I'm also not asking you guys to write me the code. I simply want to know a robust strategy to solve this problem.
Here is what I thought about:
Save the endtime in db and using a cron job check every second to see if the time is up (This is not really good in my opinion since the query and all calculations might take more than 1 second)
Somehow assign a variable to setInterval and store them in a global list
Your web app would have a more responsive UI and your backend would scale better if each client held its own timer. Closing the browser wouldn't be a problem.
Persist the endtime in a DB in your server for the specific question.
On the client side, retrieve the endtime from the server, and use JavaScript to create a timer that would alert the user their time has expired.
On the server side, have an additional check that rejects answers if the answer is being submitted past endtime to prevent clients from cheating.

Synchronized Timer on hundreds of Meteor Clients

Recently, I started developing a sports app using the Meteor platform. The app synchronizes scores of sports matches to connected clients in real-time (currently soccer matches). On each client, the current match time is shown as countdown (see screenshot of client).
The server updates the match time every second and clients subscribe to match+match time. Since the match time is a reactive variable, it needs to be published/subscribed every second. With only a few clients this is not a problem. But if thousands or even hundreds of clients subscribe, it will slow down the server, result in hanging countdowns etc...
I am searching for a proper solution on how to implement a synchronized countdown with Meteor (ideally real-time) that works with a magnitude of connected clients.
Thanks!
Two packages that will be useful for you:
mizzao:timesync for synchronizing time (like ntp) between clients and the server
remocoder:chronos for creating reactive time.
Reactive time happens on the client so it doesn't burden the server. Timesync of course synchronizes both but it doesn't need to run every second.

NodeJS Queue System for Connections Past 20

I'm trying to create a queue system in NodeJS so that only 20 connections are able to access a certain page at once. Right now I'm assigning each user a unique ID using shortid and javascript localStorage (to store their ID). I want to give each user 1 minute to see the piece of content and then it boots them to "get back in line". If they have to wait it will tell them "You'll be connected in XX minutes".
Right now my process is to use http.globalAgent.maxSockets = 20; to only allow 20 people in but it's not allowing me to route them somewhere else to make them wait. My thought was to have a database of what order people are "in line". Then when a user is kicked off the page after 1 minute, the next user "in line" will be brought in and given 1 minute before they are kicked out.
I'm using MySQL to store the queue. The problem is I'm not sure how to finish the code to boot someone after one minute and make them "get back in line". Any help? Thanks!
I think you're misunderstanding the HTTP protocol. When you make an HTTP request, a TCP connection is created, but not held. You also cannot just limit the sockets for a single route. HTTP is not a persistent connection. You'll need to find another way to implement such a system. Being that HTTP is stateless and non-persistent it will be difficult to do correctly. So if you limit your maxSockets to 20, that means that you can only accept 20 requests at a time. A socket is created for a request/response, but does not persist after that even if the user is still views the page.
You'd probably need a way to "check-in" a user to that page. Something that comes to mind would be to have the users connect to a web socket when they reach that page, and each time a user attempts to join then send out a broadcast to all the users on that page to see how many are still on it. This would still be easily fooled unless you served the pages content over the websocket, because I could simple disable websockets or load a script to just disconnect from the websocket so it cannot "put me back in line". It's likely a very complicated solution, because you're trying to manage the state of your clients, and that's not something HTTP is good at on its own.

Server polling intervals for a javascript chat client

I'm building a basic little AJAX shoutbox/chat for my website, but I'm not sure exactly how to implement the server polling.
Here's the basic program flow I'm thinking of:
User comes to page and is shown the last 10 messages
To get messages sent by others, the client javascript would request a URL with a timestamp parameter (set to the value of the last message the client received)
The server returns all messages (up to a max of 10) since that timestamp.
The only issue is how often to poll the server. Obviously it should poll each time a new message is added, but when you're just reading others' messages it needs to automatically update.
Should it be a set time limit? eg: every 10 seconds. Or, should it vary depending on usage? eg: Check after 5 seconds. If there's no messages, don't check for another 10 seconds. If there's still no new messages, check in 15 seconds, then 20, up to maybe once every 30 seconds max. Each time there's a new message detected reset your timer back down to 5 seconds and start again.
I'm just concerned about putting unnecessary stress on the server, considering that we could have hundreds of users concurrently online.
...or have I got the whole thing wrong? Is there a better way to implement a basic javascript chat?
You might want to look into what are known as Comet programming techniques to stream information down to your users, rather than having the client poll the server. This is actually a family of techniques, some of which may work better than others depending on the circumstances, such as what kind of server you're using and what kind of client compatibility you need.
If your server can handle a large number of open connections at a time (as in, it does not use an entire thread or process per connection, such as nginx or an erlang based server), you may wish to use a long polling technique, where as soon one message is received, the client immediately requests another message. If there are no messages available, the server simply keeps the connection open, possibly sending occasionally dummy data as a keepalive, until a message becomes available.
Comet, described by Brian is a nice technique, but requires session support on the server, which is probably more advanced than you care to implement for a simple chat box.
The best way to implement polling intervals is to imagine you having a chat window which you can minimize to do other stuff, or open to see if you have new messages. When you are in the middle of a conversation, you'll switch to it (poll) frequently. If you don't get any messages for a while, you will start looking rarer and rarer until you only check it occasionally.
Assuming you don't need to do real-time typing, you can probably poll every 3 seconds or so when at peak activity, and if nothing shows up for 5-10 polls, start to crank the interval up (perhaps doubling it every time) until it hits 30-60 seconds. Getting a message back should reset the poll interval back to a few seconds, while sending a message should poll instantly, but probably doesn't need to effect the frequency of polling otherwise.
Honestly, if you are implementing a “basic little AJAX shoutbox/chat”, things like Jabber, Comet etc are overkill for you. These things will require you to run additional
servers/proxies to take the load of the app server and db.
When you think about stuff like presence management (“Joe is typing...”), then things get overly complex for your app (considering “chat” is not your prime focus).
Think about adding widgets from providers like Meebo and Userplane. Once you scale think about the Jabber and the like…
You should check to see if the other user is typing every 5 seconds or so, if the other user is typing, then you can check every 1 second to see if the user has sent a new message. Really though, you should be able to check every 1 second to see if other user is typing and if they are then every .25-.5 second check to see if new message has been sent. With broadband being so generally accepted on the inet, shouldn't be a problem. Go with the longer poll timeout for a dial-up access.
This is a very hard question, keep abuse in mind. Malicious users will hit you as often as possible, with the earliest timestamp faked so as to cause stress on your DB server. Be sure to validate that timestamp, or ignore it, because shouldnt everyone be in the same time anyway?
You can send the polling interval to the user as a function of the other user's response time. That's the best kind of dynamic I think.
http://jabbify.com/home/comet_service
This is a free comet based chat service by the guys who did the jmvc framework. Haven't tried it yet, but looks promising.
The professional way of doing this is with a WebSocket javascript connection. You can use a free service like https://socketsbay.com/ for example, and connect using
// Create WebSocket connection.
const socket = new WebSocket('wss://socketsbay.com/wss/v2/[ChannelId]/[ApiKey]/');
// Connection opened
socket.addEventListener('open', function (event) {
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
});
You can forget about server pooling time because it will be realtime.

Categories

Resources