Skip to content

Conversation

FumanalMiguel
Copy link

Motivation

This fork of Laravel Reverb introduces internal event dispatching for presence channel activity (subscribe and unsubscribe) at the server level. The primary motivation for this change is to overcome a limitation when using Pusher, while Pusher provides webhook support for presence channel events (like member_added and member_removed), those events are not directly observable or actionable from within the Laravel backend itself unless relying on external HTTP webhooks.

This limitation makes it difficult to:

  • Track which users are currently connected to presence channels.
  • Maintain accurate counts of connected clients.
  • Trigger internal business logic when a user joins or leaves a presence channel.

What this fork adds

This fork introduces the following improvements:

1. Custom Laravel Events for presence channels:

  • PresenceChannelSubscribe: Dispatched whenever a user subscribes to a presence channel for the first time (per user_id).
  • PresenceChannelUnsubscribe: Dispatched whenever a user fully disconnects from a presence channel (i.e., no other connections remain with the same user_id).

These events are dispatched within the InteractsWithPresenceChannels trait and provide access to:

  • The channel name
  • The Connection instance (which includes app id, socket id, etc.)

2. Better visibility and control:

With these events, your Laravel backend can now:

  • Log or audit connection activity.
  • Broadcast additional internal events.
  • Update metrics or cache based on real-time channel activity.
  • Implement custom presence tracking for dashboards or analytics.

Example: Listening to the events

You can listen to the new events like any other Laravel events:

use Laravel\Reverb\Events\PresenceChannelSubscribe;
use Laravel\Reverb\Events\PresenceChannelUnsubscribe;

Event::listen(PresenceChannelSubscribe::class, function ($event) {
    Log::info("User subscribed to presence channel", [
        'channel' => $event->channel,
        'socket_id' => $event->connection->socketId(),
    ]);
});

Event::listen(PresenceChannelUnsubscribe::class, function ($event) {
    Log::info("User unsubscribed from presence channel", [
        'channel' => $event->channel,
        'socket_id' => $event->connection->socketId(),
    ]);
});

Implementation details

The logic is located inside the InteractsWithPresenceChannels trait, where:

  • Before broadcasting member_added, the server checks if this is the first connection for that user_id.
  • Before broadcasting member_removed, the server verifies that no other connections remain for the same user_id.

This mimics Pusher's behavior while giving you full control in Laravel.

@taylorotwell
Copy link
Member

Thanks for your pull request to Laravel!

Unfortunately, I'm going to delay merging this code for now. To preserve our ability to adequately maintain the framework, we need to be very careful regarding the amount of code we include.

If applicable, please consider releasing your code as a package so that the community can still take advantage of your contributions!

@FumanalMiguel
Copy link
Author

Reconsideration Request for PR.

Hello, thank you for reviewing my pull request.

I understand and respect the decision to reject it, but I’d like to kindly provide some additional context that may warrant reconsideration.

The issue of not emitting a laravel disconnection event on presence channels when a client unexpectedly disconnects (e.g., due to network loss or browser close) is a recurring problem in the Reverb and Laravel Echo communities. Several users have raised this concern, and it has led to confusion and difficulty in reliably tracking online/offline status for authenticated users, especially in presence channels.

While there was a previously accepted PR that emits a similar event when a channel is created or closed, that solution does not fully address cases where a connection drops without an explicit unsubscribe. In those cases, the current implementation silently removes the connection without notifying other subscribers, and the member_removed event is never dispatched — making it impossible to properly handle presence state.

My proposed change mirrors the intent of the accepted PR, but targets the disconnection flow, which is equally important. I’ve also noticed that other developers have submitted PRs or opened issues regarding this same need. I will include a few references below for further context.

#226
https://www.reddit.com/r/laravel/comments/1e54ytf/users_of_laravel_reverb_how_are_you_determining/
#238
#91
#185

I believe that this implementation and others that can be carried out in the future, could highly amounted to the package for many more functionalities without much complicating the maintainability of the code

I believe adding support for emitting a proper member_removed event upon unexpected disconnections would improve the consistency and reliability of presence channel behavior, and align better with the expectations set by Laravel Echo and Pusher.

Thank you again for your time and consideration. I’m happy to make any changes needed to better align with the project’s direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants