Reputation:
I have two sets of jobs:
How can I process all the jobs in Set1 and then process the jobs in Set2?
I tried job chaining. But job chaining stops processing the jobs if its previous job is failed. I want to process them all even if one of them is failed.
It should process all the jobs in Set1(A,B,C), and the process of B and C should not stop if the process of job A failed. When all the jobs of Set1 are processed(no matter failed or succeeded) It should pick up jobs in Set2 to process.
The order of the jobs is not priority here. They can be processed in any order.
The only rule is that jobs in Set2 should only be processed after all the jobs in Set1 are processed.
I cannot work with delayed dispatch because the time taken to process Set1 of jobs varies very highly.
Upvotes: 0
Views: 5747
Reputation: 5319
This can now be done with Job Batching in Laravel 8.x:
$batch = Bus::batch([
new ImportCsv(1, 100),
new ImportCsv(101, 200),
new ImportCsv(201, 300),
new ImportCsv(301, 400),
new ImportCsv(401, 500),
])->then(function (Batch $batch) {
// All jobs completed successfully...
})->catch(function (Batch $batch, Throwable $e) {
// First batch job failure detected...
})->finally(function (Batch $batch) {
// The batch has finished executing...
})->dispatch();
Upvotes: 1
Reputation: 5552
You can dispatch them to different queues:
A::dispatch()->onQueue('set1');
B::dispatch()->onQueue('set1');
C::dispatch()->onQueue('set1');
D::dispatch()->onQueue('set2');
E::dispatch()->onQueue('set2');
F::dispatch()->onQueue('set2');
and run a worker that makes sure set1 is empty before checking set2:
php artisan queue:work --queue=set1,set2
To start a worker that verifies that all of the
high
queue jobs are processed before continuing to any jobs on thelow
queue, pass a comma-delimited list of queue names to thework
command:php artisan queue:work --queue=high,low
https://laravel.com/docs/5.8/queues#running-the-queue-worker
Edit:
You can solve set1
jobs from User2 delaying the set2
jobs from User1 by starting more workers.
Upvotes: -1
Reputation: 1848
An idea would be to create a JobSet job and a JobWorker job.
So the Job set takes your new JobWorker("A"), JobWorker("B"), JobWorker("C") as an argument and then dispatches all of them.
dispatch(new JobSet(new JobWorker("A"), new JobWorker("B"), new JobWorker("C")));
and the "JobSet" job for inspiration
class JobSet implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $a;
private $b;
private $c;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(JobWorker $a, JobWorker $b, JobWorker $c)
{
$this->a = $a;
$this->b = $b;
$this->c = $c;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
dispatch($this->a);
dispatch($this->b);
dispatch($this->c);
}
}
Upvotes: 0
Reputation: 9045
The job chaining in Laravel is based on the fact that it will no execute the next jobs if current one fails.
You can use events. Each job has 2 methods handle()
and failed()
. You can emit events either when job is executed successfully or it is failed. See below example :
For example :
<?php
namespace App\Jobs;
use Exception;
use App\Something;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class JobA implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
protected $something;
/**
* Create a new job instance.
*
* @param Something $somethin
* @return void
*/
public function __construct(Something $something)
{
$this->something = $something;
}
/**
* Execute the job.
*
* @param AudioProcessor $processor
* @return void
*/
public function handle()
{
// Execute Job on something
event(new JobAHandled($something));
}
/**
* The job failed to process.
*
* @param Exception $exception
* @return void
*/
public function failed(Exception $exception)
{
// Send user notification of failure, etc...
event(new JobAFailed($something, $e));
}
}
Now, you can call the next job by listening to events JobAHandled
and JobAFailed
. This will give you control that even if you are continuing the next job execution, you know what the earlier job failed. You can log that if needed.
Then you can do the same for other jobs independent of set it is in.
Also make sure if you try the job, then the further jobs will be executed again as considering your case the failed event will execute the next job as well.
Upvotes: 0