I am learning Laravel, working on a project which runs Horizon to learn about jobs. I am stuck at one place where I need to run the same job a few times one after one.
Here is what I am currently doing
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Subscriptions;
class MailController extends Controller
{
public function sendEmail() {
Subscriptions::all()
->each(function($subscription) {
SendMailJob::dispatch($subscription);
});
}
}
This works fine, except it runs the job's across several workers and not in a guaranteed order. Is there any way to run the jobs one after another?
What you are looking for, as you mention in your question, is job chaining.
Job chaining allows you to specify a list of queued jobs that should be run in sequence. If one job in the sequence fails, the rest of the jobs will not be run. To execute a queued job chain, you may use the withChain method on any of your dispatchable jobs:
ProcessPodcast::withChain([ new OptimizePodcast, new ReleasePodcast ])->dispatch();
So in your example above
$mailJobs = Subscriptions::all()
->map(function($subscription) {
return new SendMailJob($subscription);
});
Job::withChain($mailJobs)->dispatch()
Should give the expected result!
Update
If you do not want to use an initial job to chain from (like shown in the documentation example above) you should be able to make an empty Job
class that that has use Dispatchable;
. Then you can use my example above