Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel - Running Jobs in Sequence

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?

like image 698
Vish K Avatar asked Oct 18 '25 18:10

Vish K


2 Answers

What you are looking for, as you mention in your question, is job chaining.

From the Laravel docs

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

like image 144
Josh Avatar answered Oct 20 '25 17:10

Josh


Everything depends on how many queue workers you will run.

If you run single queue worker, those jobs will be processed in the order they were queued. However, if you run multiple queue workers, obviously they will be run in same time. This is how queues should work. You add some tasks and they might run in same time in different order.

Of course if you want to make sure there is a pause between those jobs, you could inside each add some sleep() but assuming you are running this in controller (what might be not a good idea because what in case you have million subscriptions) it might be not the best solution.

like image 39
Marcin Nabiałek Avatar answered Oct 20 '25 17:10

Marcin Nabiałek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!