Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Ability to specify the broadcaster to use when broadcasting an event #38086

Merged
merged 5 commits into from
Jul 21, 2021
Merged

[8.x] Ability to specify the broadcaster to use when broadcasting an event #38086

merged 5 commits into from
Jul 21, 2021

Conversation

clemblanco
Copy link
Contributor

@clemblanco clemblanco commented Jul 20, 2021

This PR adds an optional attribute on an Event $broadcaster which can be defined per "broadcastable" Event in order to specify which Broadcaster to use when broadcasting the said event.


As it stands, once we have configured the default "connection" to use within config/broadcasting.php we cannot use another one for a specific event.

This is due to the BroadcastServiceProvider always registering a singleton with a default connection set to null within the IoC, which means that whenever a new Event which needs to be broadcast is handled, it will resolve the Broadcaster contract from the IoC, always fetching the default broadcaster configured.

It could be quite handy to be able to have a bit more flexibility if we were to use a different broadcaster per type of event or type of clients our server-side events should broadcast to.

This is supported by:

  1. A trait InteractsWithBroadcaster adding the definition for the optional attribute as well as a method to set the broadcaster on the fly.

In a similar fashion to what we can currently do with queued jobs

class ProcessPodcast implements ShouldQueue
{
    use InteractsWithQueue;
    
    public function __construct()
    {
        $this->onQueue('processing');
    }
}

we could have the following for basic broadcast events

class OrderShipped implements ShouldBroadcast
{
    use InteractsWithBroadcaster;
    
    public function __construct()
    {
        $this->withBroadcaster('log');
    }
}
  1. An additional method on the PendingBroadcast class in order to specify on the fly which broadcaster to use.
broadcast(new OrderShipped($order))->withBroadcaster('log');
  1. Instead of fetching the Broadcaster from the IoC upon broadcast event handling, we now resolve the Manager and call connection() there using the optional broadcaster attribute. Note that we fallback to the current behaviour which prevents introducing any breaking change.

Note: Even though the "connection" term is used throughout the config/broadcasting.php file, I've decided to use "broadcaster" to prevent any confusion with the existing $connection property you can have on a queued event.

@taylorotwell
Copy link
Member

Interesting - what led you to use multiple broadcasters for your application?

@clemblanco
Copy link
Contributor Author

Thanks. From a pure Broadcasting point of view, you could need to broadcast some events using the log broadcaster for auditing purposes while keeping Pusher for others. You could also want to separate concerns and use two different broadcasters for two different client-side JavaScript applications.

What really pushed me looking into this was the fact that we are currently trying to leverage Broadcasting in order to implement some PubSub pattern between applications using SNS and SQS.

We understand Broadcasting is primarily for client-side JavaScript applications but in a PubSub context, when publishing an event to the outside world, it is literally "broadcasting" a server-side event, hence why we think Broadcasting makes totally sense.

We would like to be able to use a different broadcaster for these kind of PubSub events while keeping the ability to use Pusher for our client-side JavaScript application.

@taylorotwell taylorotwell merged commit f4bb259 into laravel:8.x Jul 21, 2021
@clemblanco
Copy link
Contributor Author

Thanks for this. Would you be happy if I start drafting some documentation for it? Or is it something you prefer to do internally?

@carltondickson
Copy link

carltondickson commented May 3, 2022

For anyone upgrading Laravel 7 -> Laravel 8 and getting broken tests, e.g.

TypeError: Argument 1 passed to Illuminate\Broadcasting\BroadcastEvent::handle() must be an instance of Illuminate\Contracts\Broadcasting\Factory, instance of Mockery_0_OurApp_Broadcast_Broadcasters_GoogleBroadcaster given

Take a look at the way the test were updated in this diff...

https://github.com/laravel/framework/pull/38086/files#diff-feb39f42d76515221e9edfa1b8239c0f88f2561065f165ec69978e0eec1616dd

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.

3 participants