我正在学习Laravel,正在做一个运行Horizon的项目来学习工作。我被困在一个地方,我需要一个接一个地运行相同的工作几次。
这是我目前正在做的事情
<?php
namespace AppHttpControllers;
use AppHttpControllersController;
use AppModelsSubscriptions;
class MailController extends Controller
{
public function sendEmail() {
Subscriptions::all()
->each(function($subscription) {
SendMailJob::dispatch($subscription);
});
}
}
这工作正常,除了它在多个工作人员之间运行作业并且不按保证的顺序运行。有没有办法一个接一个地运行作业?
正如您在问题中提到的,您正在寻找的是工作链。
来自拉拉维尔文档
作业链允许您指定应按顺序运行的排队作业的列表。如果序列中的一个作业失败,则不会运行其余作业。要执行排队的作业链,您可以在任何可调度作业上使用 withChain 方法:
ProcessPodcast::withChain([ new OptimizePodcast, new ReleasePodcast ])->dispatch();
所以在你上面的例子中
$mailJobs = Subscriptions::all()
->map(function($subscription) {
return new SendMailJob($subscription);
});
Job::withChain($mailJobs)->dispatch()
应该给出预期的结果!
更新
如果您不想使用初始作业进行链接(如上面的文档示例所示(,您应该能够创建一个具有use Dispatchable;
的空Job
类。然后你可以使用我上面的例子
一切都取决于您将运行多少队列工作线程。
如果运行单队列工作线程,则将按排队顺序处理这些jobs
。但是,如果您运行多个队列工作线程,显然它们将同时运行。这就是队列应该如何工作。添加一些任务,它们可能会以不同的顺序同时运行。
当然,如果您想确保这些jobs
之间有暂停,您可以在内部each
添加一些 sleep((,但假设您在控制器中运行它(这可能不是一个好主意,因为万一你有百万订阅(它可能不是最好的解决方案。
你需要的是作业链。
您可以在Laravel网站上阅读所有相关信息: 链条
祝你好运
要添加有关@Josh答案的额外信息,如果您的一个作业IlluminateContractsQueueShouldQueue
接口实现,则链中的其他作业必须实现ShouldQueue
接口,否则它们将不会链接。
例如,这里如果类ProcessPodcast
实现ShouldQueue
,OptimizePodcast
也必须实现这个接口才能包含在链中。
class ProcessPodcast implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
...
}
class OptimizePodcast implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
...
}