laravel / reverb

Laravel Reverb provides a real-time WebSocket communication backend for Laravel applications.
https://reverb.laravel.com
MIT License
1.07k stars 82 forks source link

Add backend listener for presence channel events to log user attendance #185

Closed xaniuskarlhall closed 5 months ago

xaniuskarlhall commented 5 months ago

I am using this package to handle WebSocket connections and manage presence channels for a livestream feature in my application. I would like to log user attendance by tracking when users join or leave the livestream. Is there a way to set up a listener or hook in the backend to capture the events when a user joins or leaves a presence channel? Ideally, I would like to be able to:

  1. Detect when a user joins a presence channel and log their user ID, timestamp, and any other relevant information to track their attendance.
  2. Detect when a user leaves a presence channel (either by explicitly leaving or due to disconnection) and log the corresponding information to mark the end of their attendance.
  3. Store these attendance logs in a database or suitable storage mechanism for later analysis or reporting.

If there is a built-in way to achieve this using the Reverb package, please let me know. Otherwise, I would greatly appreciate any guidance or suggestions on how I can extend the package or implement a custom solution to log user attendance based on presence channel events.

joedixon commented 5 months ago

You could inspect the MessageReceived event, which fires every time a user sends a message (such as requesting to join a channel). However, be wary that any action you carry out when this event is fired will block other messages flowing through the server from being processed.

FojleRabbiRabib commented 5 months ago

But, currently, there is no event similar to pusher:unsubscribe. How can disconnection events be handled?

joedixon commented 5 months ago

Reverb handles the unsubscribe event: https://github.com/laravel/reverb/blob/78056b18086a5dcd0c50db8398e9be313e22624b/src/Protocols/Pusher/EventHandler.php#L35

Merraclius commented 4 months ago

Hello @joedixon, I have a similar problem, I'm trying to use Reverb for detecting the "online" state of users. But what I see, is that Reverb handles unsubscribe events, which we can listen to through MessageReceived, but we can't listen to unsubscription event which is invoked after client disconnection https://github.com/laravel/reverb/blob/f0cee423dce0ed8c8d65dbfdfc531b188627a50d/src/Protocols/Pusher/Server.php#L76 As a result, we can't detect when the user goes to "offline" status

joedixon commented 4 months ago

Thanks @Merraclius - can you provide a scenario where the unsubscription event which is invoked after client disconnection?

Merraclius commented 4 months ago

The most simple case.

  1. User open the page, we joining him to presence room.
  2. He close the tab/window Reverb catch the connection close event which fire unsubscribe event. But this event only broadcasting the information about unsubscription to other clients (through broadcastInternally) but can't be catched inside our application
joedixon commented 4 months ago

Reverb will still dispatch the MessageReceived event, so you can hook into that?

Merraclius commented 4 months ago

No, because MessageReceived is dispatched only on receiving the message https://github.com/laravel/reverb/blob/f0cee423dce0ed8c8d65dbfdfc531b188627a50d/src/Protocols/Pusher/Server.php#L67, but in this case, the Reverb server doesn't receive any messages. It just detects that the connection is closing and no messages

joedixon commented 4 months ago

Gotcha - that's handled by the close method rather than on message receipt

https://github.com/laravel/reverb/blob/main/src/Protocols/Pusher/Server.php#L73-L85

I'll give this some thought, but I'm wary of adding more events due to the potential to block the event loop.

Thank you for the additional feedback 👍

jakubforman commented 4 months ago

It would be great to be able to catch and somehow react to connection termination directly on the server. For example, it would be possible to create a dashboard with real-time information about the status of devices if they are online or offline (2 frontend applications in total - administration app and device app).

Maybe I'm wrong now, but I've been solving this very problem with event trapping and connection termination for about a week now. For example, if I have information about device changes under company.{companyId}, but I can detect connection closure on device.{deviceId} then I can send a message to company.{companyId} that the device is already offline or online or other data and notify administration app. Thus, a dashboard that lists all devices under company (1:N) would have only one open WS connection and would not need to implement N connections + Heatbeat + CRON to detect device disconnection.

I also tried PresenceChannel, but the current implementation is more for chat applications and cannot be used for anything else since it is built directly on user ID and this authorization. This greatly limits the possibilities, as for example there may be a 1:N binding where there are N devices under 1 company, and in the company I want to see which devices are currently online or offline.

If you have any ideas on how to achieve this without the "Heartbeat + CRON" of the app representing the device, that would be great.

jakubforman commented 4 months ago

I have created a fork and will prepare a PR when I add more event features, tests and I am sure it works fine. If you want to test the functionality of the event that is called when a connection is closed Laravel\Reverb\Events\ChannelDisconnected; https://github.com/jakubforman/reverb

IggsGrey commented 2 months ago

Since https://github.com/laravel/reverb/pull/206 was closed, are we looking at any other alternatives for logging user attendance (AKA detecting user online status)? besides monitoring events.

Could we, for instance, get the number of people in a channel?

IggsGrey commented 2 months ago

@joedixon

sharaizk commented 1 month ago

@joedixon, It would be highly beneficial to have an event listener for connection and disconnection events within Reverb. This enhancement would significantly broaden the utility of Reverb, like it can help in handling the statuses of the users 👍