Emit a lot of messages vs join a lot of rooms - sockets

Socket.io offers first-class support to address specific recipients by using rooms
I'm creating a webapp where the server passes notifications to the user via Socket.io. It is a marketplace. Users may favourite/buy/sell articles and will therefore be notified from the server when something changes.
Now I've got to make the choices whether a user joins a room for every article he is interested upon login or whether I emit a message for every user individually when something changes.
What is more efficient? Is there a best practice? Am I taking on this problem from the wrong perspective?

Rooms are only a construct on the server for keeping track of lists of sockets. When you broadcast to a room, all the socket.io code does is loop through the list of sockets and send a message individually to each one.
So, in either of your cases, a message is being sent individually to each socket - same for both. Use rooms if the mechanism for keeping track of groups of sockets and being able to easily send a message to each one is useful and works for your purpose.
If you have some reason to want to use your own data structures for keeping track of lists of sockets, then that's fine too and it won't cost any more to loop through it and send a message to each one as long as you have an efficient scheme for finding which sockets you want to send the message to.

Related

Application Advise: SSE vs. WebSockets

I'm writing an application in which users will be able to send money to each other. I've built out most of it, but now comes the most important part, managing transactions as they occur.
What I'd like to do upon a successful transaction is to send an update to the recipient. Right now, my thinking is to do this via SSE or WebSockets. For this particular app, it doesn't appear that I need bi-directional communication, since the response would only be sent to the recipient's instance which should be listening for a response from the server.
I might be answering my own question here, but I also wanted to factor in scale. If my app grows to a million users, for instance, which technology would best be able to handle the number of transactions being processed without failure?
I'm also a little unsure as to how to implement this for the case where there is a multiplicity of users, but I only want a particular user to receive the update.
Any advise would be greatly appreciated.
Thanks!

XMPP for multiplayer feature - design question

There is a game that currently is played on standalone computers.
I want to create an add-on that allows the players to interconnect. For that I think XMPP seems to be a suitable platform.
The messages that shall be exchanged is presence/roster so users can find each other, structures messages to send items or money and generic text messages for comment and fun. In later versions I'd like to experiment with some 'business logic' to send out global changes for the world or missions and such.
My question is how users get hooked up to each other. Imagine someone creates an XMPP account. How does he start meeting the others?
Or, in general how would the users see each other if they have independent accounts? Should they all join one first multi-user-chat? Should there be one monitoring component to send invites and update rosters?
If, inside the game players can enter different areas, would it make sense to have one multi-user-chat per game area?
I know these are many questions but maybe from them you get the design problem I am facing, and I'd be happy to get some clues how this could get implemented.
Meanwhile I found the answer.
The game acts as XMPP client. It sill connect automatically to a multi-user-chat that is hardcoded in the game. With the correct parameters given, the XMPP server will create the chat room on the first user to connect. Subsequent users will simply join the same room.
This given, every user will automatically receive presence messages for all users in that room. From this the client knows the other player's addresses and can send messages to specific players. Messages addressed to the room will automatically be relayed to all other users.
So the problem I saw above is actually very easy to solve within XMPP.

ejabberd 2 user MUC vs. normal 1-to-1 chat

I've been working with ejabberd for some time now, but due to some recent issues and requirements, I'm curious about something.
If I create a MUC room with 2 users in it, does it differ from normal 1-to-1 chat messaging (performance wise)?
What happens if I always use MUCs for all 1to1 chats?
Does it have any performance overheads or disadvantages?
Do my connections suffer from performance penalties, and does this generally consume more resources or impose any kind of restrictions or penalties?
Any help or insights would be much appreciated.
I don't know how ejabberd implements XMPP, but from protocol perspective:
"Normal" one-to-one chats are stateless server-side. All context (message history etc) is maintained by client. Server just relays messages back and forth. On the other hand, Multi User Chats are maintained by server. Resources (participants list, room settings, message history) have to be stored somewhere, and that responsibility lies on server.
One to one messages are "ad-hoc". When one party wants to chat, they just send a message to recipient. MUC, on the other hand, has to be created, configured prior to starting conversation, and the other party has to be invited to join MUC room before conversation can begin. This adds complexity and/or time.
Multi User Chats give more features, but it is debatable whether they make sense in context of one-to-one conversations (eg. does kicking someone out of conversation make sense?). On the other hand, you probably have to properly configure chatrooms, so that they are not discoverable (one cannot see list of conversations), third parties cannot join them (unless invited to), that users cannot freely change nicknames etc.
Yes, MUC has an overhead which is the MUC process management itself.

Persistent XMPP MUC (XEP-45), like WhatsApp groupchats

From the spec —
7.14 Exiting a Room
In order to exit a multi-user chat room, an occupant sends a presence
stanza of type "unavailable" to the <room#service/nick> it is
currently using in the room.
Example 80. Occupant Exits a Room
<presence
from='hag66#shakespeare.lit/pda'
to='coven#chat.shakespeare.lit/thirdwitch'
type='unavailable'/>
This implies that as soon as the user disconnects from the XMPP server, he is removed from the group on the server side. The issue is simple — I don't want this behavior; I want a behavior that is similar to what Whatsapp does, i.e. even if the user goes offline, he is still part of the MUC room (which is configured to be persistent on the server side) and will receive messages from other occupants.
Given the spec and the documentation for XEP-0045 and XMPPFramework for iOS, I have no idea how to accomplish this or if it's possible to accomplish this in the traditional ejabberd server.
XEP-45 was designed more then 10 years ago. Back then, the designers had something like IRC channels in mind. Everything of XEP-45 is designed based on the assumption that a user enters and leaves a room when he/she starts/terminates its client.
WhatsApp Groupchats are different: A user joins a groupchat is is able to view the (complete) history of that chat. Even if the users client is offline/unavailable, he is still considered part of the groupchat.
The XMPP community currently works on a new XEP that provides such functionality. It is called XEP-0369: Mediated Information eXchange. It is the spiritual successor of XEP-0045, providing the features one would expect from modern groupchats.
You could emulate something quite like this by using server-side history of the MUC (Message Archive Management, XEP-0313), so that when a client logs in they're able to request the history of the MUC while they weren't in it.
If you also want to be able to show the offline pseudo-occupants of a room, the easiest way to do this is probably to map a pubsub node per room to store the list of these pseudo-occupants that clients could read to supplement the usual occupancy list.
There are probably other solutions here, but those that come immediately to mind for me involve changing the behaviour of the server in non-standard ways, such as allowing normal occupants to query a membership list, which normally only admins can do.
The Whatsapp model is much simpler than you imagine - they just maintain user session online even if user disconnects, and re-sends messages when he "reattach" session. XEP-0198 introduce similar concept to traditional XMPP sessions. You only need to configure longer inactivity period (typically XEP-0198 assume 300 seconds, but whatsapp-like messengers holds session 24+ hours)
Yes you can make your group persistent by setting its configurations this way:
NSString *var = [field attributeStringValueForName:#"var"];
if ([var isEqualToString:#"muc#roomconfig_persistentroom"])
{
[field removeChildAtIndex:0];
[field addChild:[NSXMLElement elementWithName:#"value" stringValue:#"1"]];
}

XMPP: adding bidirectionality to pubsub?

I am not sure if pubsub or multiuserchat is the way to go?
What I think I need is pubsub, but with the added ability for subscribers to broadcast messages to the feed as well. Bidirectional information flow, if you will.
The use case is such that subscribers will be subscribed to on average 1000 different feeds, but each individual feed only broadcasts information on average once per week. So, lots of feeds, but low activity in each one. However, b/c there are 1000 different active subscriptions, a subscriber might still be notified of 100 messages per day, and they should be able to "reply" aka post content to any one of those feeds.
It seems like what I need is a pubsub/multiuserchat hybrid. But that doesn't exist, or does it? Any ideas or pointers?
Thanks a bunch!
If a subscriber is publishing data then they are not just a subscriber, they are a publisher. And there is no reason the same entity can't be a publisher and a subscriber at the same time.
As for your more general question about pubsub vs. MUC, that's a question that I find comes up a lot nowadays.
Obviously at first glance MUC and pubsub are very similar, they are both about broadcasting to a group. Many applications could easily use one or the other with no trouble.
To help decide which fits best with your applications, let's go through some of the differences between the two protocols.
MUC:
Is absolutely good for standard chatrooms of online users communicating with each other. If this is what you're doing, use it.
Includes presence, i.e. notifying other occupants about joining, leaving and changing status.
Allows for anonymous private communication between occupants.
Works out of the box with practically any standard XMPP client (for standard chat messages).
Automatic leaving of the room when the user goes offline or disconnects.
Messages with custom payloads are supported, meaning you are limited to routing standard chat messages.
Pubsub:
One or a few publishers transmitting to many read-only subscribers is core pubsub territory. In contrast to MUC the subscribers are not publishing, and are not receiving information about other subscribers.
Server implementations tend to have much more flexible access control for pubsub.
Custom payloads only, no standard chat messages.
Optionally has full item persistence.
A node can be managed as a list of items (ie. add/remove with notification) rather than just simple broadcast.
Subscriptions can persist through being offline.
The points above are just a guide. A lot can typically be achieved through server configuration. As an example, the MUC specification allows for rooms withholding presence broadcasts for certain classes of occupants based on configuration. The catch here is in the implementations... since this is an uncommon usage of MUC, you will find it may not be supported in many MUC implementations. The point being that as MUC was designed for chatting and not generic pubsub, you will largely find all the implementations and tooling around MUC to focus on that kind usage.
Not sure what the problem is. The subscriber simply needs to be a publisher as well. There is nothing stopping them from publishing as well as subscribing (unless the nodes are configured to disallow it).
This appears to be a very typical pubsub case.