BrainBoxLabs / brain-socket

Websockets for event-driven laravel apps.
589 stars 75 forks source link

Messages sent to Laravel fire the event n = # of connections times #6

Open acedude opened 10 years ago

acedude commented 10 years ago

As the title says, when I send (let's say) a chat message:

app.BrainSocket.message('gather.chat.send', {id: id, text: text});

That fires an event in Laravel:

 Event::listen('gather.chat.send', function ($clientData) {

the event is executed n = # of connections times and then the response is returned to each client.

So if we have, let's say, 1000 clients, this would run the event 1000 times, causing HUGE amount of work (DB queries etc). Is there a way to avoid this? After all all we need is running:

 return BrainSocket::message();

for each client, instead of the whole event.

dalesbit commented 10 years ago

the solotuin is easy: Open BrainsocketEventListener and modify onMessage method.

I used to solve this problem by adding "rooms" for the connections, and ask them for handshake for a specific room, after that i can easily send messages for just the rooms.

i use event for different callback, and use rooms to store client resource id-s ;)

acedude commented 10 years ago

Hmm yeah, that would help I think, but I don't really want to fork this thing. Rooms are a good idea, it should be default behaviour.

But anyway this would not solve the problem - running the event for n = nr of connection times. I used caching (and probably I should write a pre/post hooks to simplify it), that helps a lot, but it's a hack.

dalesbit commented 10 years ago

The problem is basicly up on the event system

let me show you how i do it: -removed events, event listeners -applyed multi route via new rachet -removed object storages, we dont need so much crap -added a new handshake object (if a connection is made, the user inmediatly handshaked a room its handfull for live notifications btw, request and what can be done by it

so now ive got:

client connections which has been purified (custom connection interface) which is only up for 1 event (or i would say there is no such thing) and replaced it with a routing system i added a simple array to hold users in rooms, and because im usin a clear connection storage i dont need to loop over them just call one by one

like: $this->_Rooms->send(msgtosend); the the room object will send messages like this:

public function send($data, $interval = null){ if($interval != null) foreach($this->_Storage as $conn) $conn->send($data); else for($index = $interval['start'; $i <= $interval['end']]; $i++) $this->_Storage[$i]->send($data); }

its a markup, the real code is similar but not the same as this ;)

if u need help with it, send it over, and ill try to help

tuurbo commented 10 years ago

@acedude Its pretty simple to fire an event once.

goto BrainsocketEventListener and modify onMessage method.

change this...

foreach ($this->clients as $client)
{
    $client->send($this->response->make($msg));
}

to this...

$resp = $this->response->make($msg);

foreach ($this->clients as $client)
{
    $client->send($resp);
}

@eisenmaxx if you don't mind I'd like to see more on how you creating rooms with a handshake, etc... Maybe in a pastebin?