dispatch()
at the end of processing, like this: class MyFirstJob extends Job { use DispatchesJobs; protected $data; public function __construct($data) { $this->data = $data; } public function handle() { $this->doSomething($this->data); $this->dispatch(new MySecondJob($this->data)); // Second task } }
class MySecondJob extends Job { use DispatchesJobs; protected $data; public function __construct($data) { $this->data = $data; } public function handle() { $this->doSomething($this->data); if ($this->someCondition($this->data)) { $this->dispatch(new MyThirdJob($this->data)); // Third task } } }
dispatch()
calls) into a separate code. Then everything will be logical and clear - here we have a business process (control code, queue manager), here we have its individual pieces (queues). <?php namespace App\Jobs\Pipeline; use App\Jobs\Job; use Illuminate\Foundation\Bus\DispatchesJobs; abstract class PipelineAbstract { use DispatchesJobs; /** * @param array $params * @return PipelineAbstract */ public function start(array $params) { $this->next(null, $params); return $this; } /** * @param Job $currentJob * @param array $params Set of parameters for starting new jobs */ abstract public function next(Job $currentJob = null, array $params); /** * @param Job $job */ protected function startJob(Job $job) { $this->dispatch($job); } }
next()
method, we will just implement the business process. startJob()
is just a wrapper over dispatch()
just in case. And we will use start()
in the place where we need to initiate the entire data processing process (where data from an external service arrive). <?php namespace App\Jobs\Pipeline; use App\Jobs\Job; use App\Jobs\MyFirstJob; use App\Jobs\MySecondJob; use App\Jobs\MyThirdJob; class ProcessDataPipeline extends PipelineAbstract { /** * @inheritdoc */ public function next(Job $currentJob = null, array $params) { // Start first job if ($currentJob === null) { $this->startJob(new MyFirstJob($params, $this)); } if ($currentJob instanceof MyFirstJob) { $this->startJob(new MySecondJob($params, $this)); } if ($currentJob instanceof MySecondJob) { if ($this->someCondition($params)) { $this->startJob(new MyThirdJob($params, $this)); } } } }
MyFirstJob
. $this->dispatch(new MyFirstJob($data));
(new ProcessDataPipeline())->start($data);
next()
method. $this->dispatch(new MySecondJob($data));
$this->next($data);
<?php namespace App\Jobs; use App\Jobs\Pipeline\PipelineAbstract; abstract class Job { /** * @param array $params */ public function next(array $params) { if ($this->pipeline) { $this->pipeline->next($this, $params); } } }
next()
method call) are processed by the desired implementation of the pipeline. class MyFirstJob extends Job { /** * @param mixed data * @param PipelineAbstract|null $pipeline */ public function __construct($data, PipelineAbstract $pipeline = null) { $this->data = $data; $this->pipeline = $pipeline; } }
withChain()
, it guarantees the execution of tasks in strict sequence. In simple cases this will be enough. But in cases when there are conditions for launching one process or another, when data for the next process are born in the previous one, a more universal mechanism is still needed. For example, the one that I talked about in this article.Source: https://habr.com/ru/post/354364/
All Articles