NameUnknown's avatar

Dispatch queueable event from another job

When I dispatch a job that adds an entry to database, I as well need to dispatch events related to the newly created model. The operations performed by event listeners are quite time-consuming (which is why I queue them). The listeners implement ShouldQueue. They work well in queues when I dispatch events from a regular controller (not jobs).

But when I dispatch the events from the job, the listeners run within the same job. Due to time-consuming DB queries (which are supposed to run within a separate task) queue handler deems the job failed and dispatches it again (but the previous job is then successfully completed and marked as done).

I dispatch events within a job like this:

event(new ModelCreated($data))

And the listener (which is queueable) runs within this job thus increasing time.

I know that I can increase timeout for the job. Bu is there a way to run the listeners as a separate job from the current job?

0 likes
2 replies
LaryAI's avatar
Level 58

Yes, you can dispatch a queueable event from another job. You can use the dispatch() method to dispatch the event to the queue. Here's an example:

use App\Events\ModelCreated;

class MyJob implements ShouldQueue
{
    public function handle()
    {
        // Create the model
        $model = Model::create([...]);

        // Dispatch the event to the queue
        dispatch(new ModelCreated($model));
    }
}

This will dispatch the ModelCreated event to the queue, and the event listener will be executed in a separate job. You can also specify the queue on which the event should be dispatched by passing the queue name as the second argument to the dispatch() method. For example:

dispatch(new ModelCreated($model))->onQueue('events');

This will dispatch the event to the events queue.

NameUnknown's avatar

@LaryAI You have a point, but calling the dispatch helper on an event causes error because there is no __invoke method. But you can use the static dispatch method of the event:

ModelCreated::dispatch($model)

And it will work fine.

Thanks!

Please or to participate in this conversation.