您可以使用Queue::looping()
用于暂停整个队列或连接(而不仅仅是单个作业类)的事件侦听器。与其他方法不同,这将not当队列暂停时,将每个作业放入弹出/重新排队的循环中,这意味着尝试次数不会增加.
这是文档所说的:
使用looping
方法上的Queue
外观,您可以指定
在工作人员尝试从中获取作业之前执行的回调
一个队列。
https://laravel.com/docs/5.8/queues#job-events https://laravel.com/docs/5.8/queues#job-events
这是什么doesn't文档很好的是,如果回调返回false
then 该工人不会再找其他工作 https://github.com/laravel/framework/blob/e5a8b2d/src/Illuminate/Queue/Worker.php#L175。例如,这将防止default
运行队列:
Queue::looping(function (\Illuminate\Queue\Events\Looping $event) {
// $event->connectionName (e.g. "database")
// $event->queue (e.g. "default")
if ($event->queue == 'default') {
return false;
}
});
注:queue
该事件的属性将包含工作进程启动时来自命令行的值,因此如果您的工作进程正在检查多个队列(例如artisan queue:work --queue=high,default
) 那么值queue
如果发生的话将会'high,default'
。作为预防措施,您可能想用逗号分解字符串并检查是否default
在列表中。
例如,如果您想创建一个基本的断路器 https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern暂停mail
当您的邮件服务返回维护错误时排队,那么您可以在您的邮件服务中注册一个像这样的监听器事件服务提供者.php:
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
Queue::looping(function (\Illuminate\Queue\Events\Looping $event) {
if (($event->queue == 'mail') && (cache()->get('mail-queue-paused'))) {
return false;
}
});
}
这假设您在应用程序的其他地方有一个机制来检测适当的情况,在本例中,该机制需要为mail-queue-paused
共享缓存中的密钥(因为这就是我的代码正在检查的内容)。有更强大的解决方案,但在缓存中设置特定的众所周知的密钥(并自动使其过期)很简单并且可以达到预期的效果。