Jua*_*gel 5 foreach nested laravel
我创建了一个作业,它有一个 foreach 循环来调度另一个作业。有没有办法在所有嵌套作业完成后触发?
当这里触发时发生了什么
步骤 1. 首先我触发批处理作业
GenerateBatchReports::dispatch($orderable);
第 2 步。然后我们运行一个循环并将其他作业排入队列
/**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $dir = storage_path('reports/tmp/'.str_slug($this->event->company) . '-event');
        if(file_exists($dir)) {
            File::deleteDirectory($dir);
        }
        foreach($this->event->participants as $participant) {
            $model = $participant->exercise;
            GenerateSingleReport::dispatch($model);
        }
    }
我只需要知道所有嵌套作业何时完成,以便我可以压缩报告并将它们通过电子邮件发送给用户。当批处理作业完成对所有嵌套作业的排队后,它将从列表中删除。有没有办法在嵌套作业完成之前保持作业,然后触发事件?
任何帮助,将不胜感激。
更新:Laravel 8(计划于 2020 年 9 月 8 日发布)将提供作业批处理。此功能已记录在案,可能非常适合嵌套作业场景,如下所示:
\n$batch = Bus::batch([\n    new ProcessPodcast(Podcast::find(1)),\n    new ProcessPodcast(Podcast::find(2)),\n    new ProcessPodcast(Podcast::find(3)),\n    new ProcessPodcast(Podcast::find(4)),\n    new ProcessPodcast(Podcast::find(5)),\n])->then(function (Batch $batch) {\n    // All jobs completed successfully...\n})->catch(function (Batch $batch, Throwable $e) {\n    // First batch job failure detected...\n})->finally(function (Batch $batch) {\n    // The batch has finished executing...\n})->dispatch();\n我们还可以动态添加额外的批处理作业:
\n$this->batch()->add(Collection::times(1000, function () {\n    return new ImportContacts;\n}));\n我想出了一个不同的解决方案,因为我有一个使用多个进程的队列。所以,对我来说:
\ndispatchNow,因为我想保持作业并行运行。因此,满足要求的我不太优雅的解决方案是分派所有嵌套作业,并且在最后一个作业中,延迟几秒钟分派最终作业,以确保可能仍在并行运行的所有其他嵌套作业将被终止。
\n/**\n     * Execute the job.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $last_participant_id = $this->event->participants->last()->id;\n\n        foreach($this->event->participants as $participant) {\n            $is_last = $participant->id === $last_participant_id;\n\n            GenerateSingleReport::dispatch($model, $is_last);\n        }\n    }\n并在GenerateSingleReport.php
class GenerateSingleReport implements ShouldQueue\n{\n    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;\n\n    protected $model;\n    protected $runFinalJob;\n\n    public function __construct($model, $run_final_job = false)\n    {\n        $this->model = $model;\n        $this->runFinalJob = $run_final_job;\n    }\n\n    public function handle()\n    {\n        // job normal stuff\xe2\x80\xa6\n\n        if ($this->runFinalJob) {\n            FinalJob::dispatch()->delay(30);\n        }\n    }\n}\n我\xe2\x80\x99m抛出了另一个想法,所以代码并不是完美无缺的。也许可以创建一个包装作业并专门用于运行与最终作业链接的最后一个嵌套作业。
\n/**\n     * Execute the job.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $last_participant_id = $this->event->participants->last()->id;\n\n        foreach($this->event->participants as $participant) {\n            $is_last = $participant->id === $last_participant_id;\n\n            if ($is_last) {\n                ChainWithDelay::dispatch(\n                    new GenerateSingleReport($model), // last nested job\n                    new FinalJob(), // final job\n                    30 // delay\n                );\n            } else {\n                GenerateSingleReport::dispatch($model, $is_last);\n            }\n        }\n    }\n并且在ChainWithDelay.php
class ChainWithDelay implements ShouldQueue\n{\n    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;\n\n    protected $job;\n    protected $finalJob;\n    protected $delay;\n\n    public function __construct($job, $final_job, $delay = 0)\n    {\n        $this->job = $job;\n        $this->finalJob = $final_job;\n        $this->delay = $delay;\n    }\n\n    public function handle()\n    {\n        $this->job\n            ->withChain($this->finalJob->delay($this->delay))\n            ->dispatchNow();\n    }\n}\n对于 Laravel >= 5.7
您可以使用该dispatchNow方法。这将使父作业在子作业处理时保持活动状态:
https://laravel.com/docs/5.8/queues#synchronous-dispatching
家长工作:
public function handle()
{
    // ...
    foreach($this->event->participants as $participant) {
        $model = $participant->exercise;
        GenerateSingleReport::dispatchNow($model);
    }
    // then do something else...
}
适用于 Laravel 5.2 - 5.6
您可以使用以下sync连接:
https://laravel.com/docs/5.5/queues#customizing-the-queue-and-connection
确保您的连接已定义config/queue.php:
https://github.com/laravel/laravel/blob/5.5/config/queue.php#L31
父作业(注意:此语法适用于 5.5。5.2 的文档略有不同):
public function handle()
{
    // ...
    foreach($this->event->participants as $participant) {
        $model = $participant->exercise;
        GenerateSingleReport::dispatch($model)->onConnection('sync');
    }
    // then do something else...
}
| 归档时间: | 
 | 
| 查看次数: | 3062 次 | 
| 最近记录: |