Alex Harris
Alex Harris

Reputation: 6402

Not fire queued jobs with no channels?

Is there any way to suppress queued jobs from firing off a broadcast event when the channel is empty? Basically what I am noticing is that while no socket pushes will go off if broadcastOn returns [] it will still make a queued job. Is there any way to have queued jobs only get created when broadcastOn returns an array with at least one element?

Upvotes: 0

Views: 81

Answers (2)

Alex Harris
Alex Harris

Reputation: 6402

It seems in Laravel 5.4 you can now add a new method on events, broadcastWhen. All that needs to be done:

public function broadcastOn() {
    return [];
}

public function broadcastWith() {
   return count($this->broadcastOn()) > 0;
}

You can read more about how broadcastWhen is handled in the source code.

Check if event should be broadcasted by condition.

Upvotes: 0

SArnab
SArnab

Reputation: 585

You'll have to do a little manual subclassing to make this work. The queued job is created in the broadcastEvent method of Illuminate\Events\Dispatcher.

protected function broadcastEvent($event)
{
    if ($this->queueResolver) {
        $connection = $event instanceof ShouldBroadcastNow ? 'sync' : null;

        $queue = method_exists($event, 'onQueue') ? $event->onQueue() : null;

        $this->resolveQueue()->connection($connection)->pushOn($queue, 'Illuminate\Broadcasting\BroadcastEvent', [
            'event' => serialize(clone $event),
        ]);
    }
}

You can add a check here to only push the job onto the queue if $event->broadcastOn returns an array with at least one element.

Once subclassed, you will need to use the new dispatcher to fire the events. You can create a new service provider for this and bind it to the container. I'm not sure if you can overwrite the existing events instance created in Illuminate\Events\EventServiceProvider, but you can definitely create a new one.

public function register()
{
    $this->app->singleton('events-custom', function ($app) {
        return (new App\Provides\CustomDispatcher($app))->setQueueResolver(function () use ($app) {
            return $app->make('Illuminate\Contracts\Queue\Factory');
        });
    });
}

If you are using the Events facade, be sure to also update your config file to point to a new Facade that returns the key to your new CustomDispatcher. Unfortunately, the events() helper function will still return the original Dispatcher. I don't believe that can be overwritten. If you can somehow overwrite the existing events key set by Illuminate\Events\EventServiceProvider though, then you're all set.

Upvotes: 1

Related Questions