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?
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:
@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: