totaljs/framework

Question about Websocket's FrameworkController

Closed this issue · 4 comments

fgnm commented

I've planned to use websocket for a real time communication between clients and an RESTful API built with Total. In this scenario there could be many clients let's say 1/10/100k. The websocket should be a message exchange between two or a limited group of clients.
Of course any client connected has to be stored in memory, more users means more RAM, but in this use case I think that the current implementation of send and send2 functions could be improved.

I've look at Total source code here index.js@15332 and here index.js@15384

If I want to use id parameter to sand a message just to one or limited number of clients the functions performs a for-loop against every clients and skip who is in the id array or in blacklist. That's fine for broadcast with blacklist, but not in the other case. Because I know exactly which of my client has to receive the message, why loop everything?
I mean, because I know the client.id I can pick it directly in O(1) complexity from self.connections instead of actual O(n).

This is a little draft:

var clientIdMap = {};

function socket_live_notification() {
    var self = this;
    console.log("socket opened");
    
    self.on('open', function(client) {
        clientIdMap[client.user.id] = client.id;
    });
    
    self.on('close', function(client) {
        delete clientIdMap[client.user.id];
        sendTo(self, 32, {message : 'Quit: ' + client.user.id})
    });
    
    self.on('message', function(client, message) {
        console.log(message)
	});
}

function sendTo(self, id, payload) {
    var client = self.connections[clientIdMap[id]]
    client.send(payload)
}

In this example the idea is to map the user.id (object from AUTH) to the original client.id, generated by Total. In this way if the client A knows the id of the client B, they can communicate directly and server should have a significant reduction of the CPU load in case we have many clients that sands many messages.

Please let me know what do you think about and forgive me if I have made some mistakes

It's OK.

  • .send() is old very old method and it exists for backward compatibility (I want to replace it in Total.js v4)
  • your solution is OK
fgnm commented

Hi
I've found a very similar issue in schedules management here index.js@1907, as I understand all schedules are managed with an array so clearing a task could be inefficient because framework has to loop the whole array to find the right one.
I think that using an approach similar for the websockets could speed up a lot this aspect of the framework. However, this time it's a bit more difficult to fix this behavior outside framework because F.schedules is not an Object.

I hope you'll appreciate this comments and don't bother you too much 😃

Hi, not a problem. You can cache the function in SCHEDULER like this:

FUNC.myscheduleroperation = function() {
    // do something
};

SCHEDULE(...., FUNC.myscheduleroperation);

And you can call it everywhere:

FUNC.myscheduleroperation();
fgnm commented

Well yes, and what about clear the task?
I'll explain better the use case: Client A and B communicate with messages on socket. If Client A sends a particular message, Client B has to reply in 1h, if don't the server should automatically execute an action against Client A.
So, when Client A sends its message the server setup a schedule, when Client B reply this schedule has to be removed.

Currently the function SCHEDULE return just the schedule uuid and not the index of its position in F.schedules array, so the only way to remove the task, before it is executed, is to use F.clearSchedule(id). This function internally loop the array with F.schedules.remove('id', id);.

So I mean that if F.schedules would be an object like F.connections it would be much more easier to remove a schedule from queue with just delete F.schedules[id].