3

我正在学习 Laravel,正在开发一个运行 Horizo​​n 以了解工作的项目。我被困在一个地方,我需要一个接一个地运行相同的工作几次。

这是我目前正在做的事情

<?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);
        });
    }
}

这工作正常,除了它在几个工人之间运行工作,而不是在保证的顺序。有没有办法一个接一个地运行作业?

4

4 回答 4

6

正如您在问题中提到的那样,您正在寻找的是工作链。

来自 Laravel 文档

作业链允许您指定应按顺序运行的排队作业列表。如果序列中的一个作业失败,则不会运行其余作业。要执行排队作业链,您可以在任何可调度作业上使用 withChain 方法:

ProcessPodcast::withChain([
    new OptimizePodcast,
    new ReleasePodcast
])->dispatch();

所以在你上面的例子中

$mailJobs = Subscriptions::all()
    ->map(function($subscription) {
        return new SendMailJob($subscription);
    });

Job::withChain($mailJobs)->dispatch()

应该会给出预期的结果!

更新

如果您不想使用初始作业进行链接(如上面的文档示例中所示),您应该能够创建一个Job具有use Dispatchable;. 然后你可以使用我上面的例子

于 2018-10-25T18:17:54.363 回答
2

一切都取决于您将运行多少队列工作人员。

如果您运行单个队列工作者jobs则将按照它们排队的顺序进行处理。但是,如果您运行多个队列工作程序,显然它们将同时运行。这就是队列的工作方式。您添加一些任务,它们可能会以不同的顺序同时运行。

当然,如果你想确保它们之间有一个暂停jobs,你可以在里面each添加一些sleep()但假设你在控制器中运行它(这可能不是一个好主意,因为万一你有百万订阅)它可能不是最好的解决方案。

于 2018-10-25T15:14:17.823 回答
0

要在@Josh 答案上添加额外信息,如果您的一个作业实现Illuminate\Contracts\Queue\ShouldQueue了接口,则链中的其他作业必须实现ShouldQueue接口,否则它们将不会被链接。

例如,这里如果ProcessPodcast实现了类ShouldQueueOptimizePodcast也必须实现这个接口才能包含在链中。

class ProcessPodcast implements ShouldQueue {
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    ...
}
class OptimizePodcast implements ShouldQueue {
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    ...
}
于 2021-09-07T10:26:35.950 回答
0

你需要的是工作链。

你可以在 Laravel 网站上阅读所有相关信息:Chain

祝你好运

于 2018-10-26T13:12:41.887 回答