How to build friend list where user status is shown online/offline? - node.js

I've 2 ideas.
Idea #1:
Using Redis put people currently online into set. Then from client side user would periodically send a request to send him status for all of his friends. Server would make sql request to get all friends and find them in the redis set and if so then they are online.
Idea #2:
Using Redis PubSub, when you as a user are online you subscribe to all n friend channels. And whenever a user goes online he publishes on a channel that he or she is online. And whoever maybe listening will get notified.
Now I can't tell which one is more scalable and efficient.

I think idea #1 should be the solution. idea #2 CANNOT work.
Redis doesn't keep published messages. So if a client is NOT connecting to Redis, the message will be lost. When he reconnects to Redis, he won't receive any messages published before.
In your case of idea #2, when a user logs in, he has no idea whether his friends are already online. Because his online friends have published online messages before he logs in, and he won't get these messages.

Related

Socket.io handle online/offline status

I've a real time chat application i've implemented it using socket.io, nodejs and angularJS but i'm having issues while handling the online/offline status. I'm not clear on how to know when the user is online or offline. What i thought is hitting a api in every 3 seconds and update the online/offline status in the database but i don't feel it's a good way so is there any better way to handle it?
Thanks in advance!
Here is the link to my backend code.
DesktopChat-Backend
You don't need to hit every 3 seconds , socket.io do this automatically, so you have just to handle it inside on. ('connection') and on.('disconnect'), so you get the user connected or disconnected then you broadcast the information to the clients, and update their status.
Look at this example :
Showing online users using Nodejs and Socket.io and angular js
One-to-One-Chat-using-Node.js-Socket-IO-Library
you can make map, where your userId will be associated with all socket.io client ids for this user. Then you can just look into this map, if specific user has some open connections.

How can I securely implement a notification system using socket?

I am currently working on a web application using the MEAN stack. It has a social aspect to it so I want to be able to push notifications to users.
The way I do it now is when something happens that should be a notification it gets stored in a mongo database with an unread flag. Each client will send a get request to the server every 30 second and will receive every notification marked as unread, and will then mark it as read.
I want to switch to using a message queue and sockets so less network resources will be used, and also provide the user with a real-time experience. I've thought about using redis and its pubsub structure but I can't seem to figure out how to do this securely. If I push out notifications to the affected users, won't it be easy for someone malicious to subscribe to somebody else's channel and receive notifications not meant for them? Am I missing something or is it just the wrong approach for such a system?
Edit: Figure I update with the solution I went with if anyone else reading this is having the same problem.
Instead of using rabbitmq, as the answer suggested, I figured that a much more easy and elegant solution is to just use socket.io. When new sockets connects to the server I save a mapping from the userID to the socketId in a redis in-memory DB. (After I've validated their token) That way, if I need to push a notification to a user I just look up the socketId in the redis DB, and then send it to the correct socket.
This way I don't need any security beyond that as socketIDs are unguessable, and the message is only sent across the single socket that belongs to the given user.
This way it will only get sent through the connection of the given socket, as socketIDs are only used server side to keep track of all the connection. This means no one else can "listen" using someone else's socketID.
you can use RabbitMQ for this. Also authentication is there. Please go through following link and try.
https://www.rabbitmq.com/access-control.html
also, you can apply authentication in existing structure using subscription auth tokens with all subscribed users only.
even redis has its security with topics. Please have a look in link below
https://redis.io/topics/security

How to use socket.io-redis Nodejs

Good afternoon,
I have a chat application written with NodeJS, Express and socket.io, in that application there are no rooms, when a user connects the socket (connection of that user) is linked to his id in an object that stays in memory:
Users = {
'1': {socket},
'2': {socket},
...
}
This works great! When a user is going to send a message it informs the recipient's id the server retrieves the equivalent socket and sends the message.
My problem is that due to the number of users I will have to upload a new server with the application, the problem is that users on different servers can not communicate because each server knows only the list of users that is connected to it. After much reading I came to the conclusion that the best way to solve this is by using the Redis Adapter, I looked for examples on the internet exhaustively however they all use Rooms to send the messages or send the same message to all the user and I would like to send one Message to a specific user regardless of which server instance it is if possible without the need to create rooms, simply recovering its connection based on its id and sending the message, would like to know if someone could tell me if this is possible and how to implement.
Below is an image of how my architecture should look:

Where/how does Skype queue group chat messages when users are offline?

In this SuperUser.com question and elsewhere, I've read that Skype doesn't store your historical chat messages on their servers in a way that's user-accessible. (Of course, what they do for internal archival and analytical purposes is a different story -- as reflected by their privacy policy).
But the user experience for group chats is: when you've been offline and you sign back into Skype... all the messages you missed appear. Even if it's been a while and there are a lot of messages. (I don't know if there are limits on how long or how many.)
So: how is this UX implemented if the messages don't come from Skype servers?
I've read this offhand description which states:
Syncing of group chats ("More than 2 people in a chat") is done by chat sync partners in those chats, and not provided by Skype servers.
If that's correct, I'd love more details about how this works, like:
Has the protocol been specified or reverse-engineered?
Is it available through an API?
Are requests routed through Skype, or is it direcly peer-to-peer?
If peer-to-peer, how are requests authenticated?
My experience is I can only "see" history back to the time when I joined a chat; can a client request or receive messages farther back in the history?
I understand some of of the protocols are currently in flux -- so, bonus points if you can explain whether/how these details are changing.
When you login your client has the last recieved id of that conversation.
Sends it to the other clients. The client who recieves the id looks up all messages after that one, and then sends it back to you.
That way they don't have to store the messages on their servers.

Socket io channel notification for each user

I am an inexperienced developer, i just started learn node.js socket.io.
I want to make notification for each user if there's post in their wall or someone has replied(commented) to the user's post, just like in the fac*book/go*gle+ notification.
I follow the tutorial here http://www.codesizzle.com/node-js-and-socket-io/
I'm combining it with laravel4 and redis as the handler that publish the message/notif to redis, then nodejs will listen to redis and if there's post/event then send it using socket io to user's browser
Based on my understanding, example:
userA posts something to userB
userB receive the notif that says "user A has posted something on your wall"
to achieve this:
I need to make userB subscribes to its own channel, maybe using his id
then when userA post something, laravel4 will receive the ajax post data
laravel insert the post to MySQL and publish the user's id + his post to redis
after that nodejs will receive the event and publish it to userB's browser.
my question is in my statement "userB subscribes to its own channel, maybe using his id." this means userB will subscribe to channel maybe notif-channel-{userId} -> notif-channel-967 , if i have thousands of users then i will have thousands of different channel, maybe from notif-channel-1 until notif-channel-50000,
will it become a problem?
what is the best practice?
does the flow already correct?
thankyou
note :sorry for the bad english.
UPDATE
After reading some more articles, i think i change the flow to:
UserA posts somethingn on UserB's wall
Then send ajax post to laravel so i can put the message/post into the db
After that emit/push event to socketio thats working on nodejs server to handle the event and push it to userB's channel, tell userB that userA has posted something
If success then notify UserA that his posts is successfull
notice that i dont involve redis in the above flow, any feedbacks?
Using sockets to do this is a pretty complicated way of doing things. It's possible, but all you really need to do is add a timed post request from that page (client side) to check for new comments.
All you really need at that point is in the db. From, To, Date, Message.
With sockets you'd have to set up a channel for each user that has a 'wall', and anyone that is viewing a persons 'wall' will have to subscribe to it, and if it's a lot of people, you will have issues when you need to expand. That means using redis with sockets.io.
While that's 'cool' to do, it's overkill in my opinion.
Build a microservice which has socket connections using caching systems and even data warehousing techniques, and at database level use triggers, when data is crud
Use parse db server which has cool feature of subscribing to live query.

Resources