如何暂停Laravel队列

时间:2017-09-10 08:36:40

标签: php laravel laravel-5.5

我有一个向远程服务发送请求的队列。有时这项服务会进行维护。我希望所有队列任务在遇到这种情况时暂停并在10分钟内重试。我该如何实现?

2 个答案:

答案 0 :(得分:4)

您可以使用Queue::looping()事件侦听器暂停整个队列或连接(而不仅仅是单个作业类)。与其他方法不同,在队列暂停时,这不会将每个作业置于弹出/重新排队的周期,这意味着尝试次数不会增加

文档内容如下:

  

looping外观上使用Queue方法,您可以指定   在工作程序尝试从中获取作业之前执行的回调   队列。

     

https://laravel.com/docs/5.8/queues#job-events

不能很好地说明的是,如果回调返回false,则返回the worker will not fetch another job。例如,这将阻止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属性将在启动工作进程时包含来自命令行的值,因此,如果您的工作进程正在检查多个队列(例如queue:work --queue=high,default),则事件中queue的值将为'high,default'

例如,如果您有一个要暂停的mail队列,则可以在 EventServiceProvider.php 中注册这样的侦听器:

/**
 * Register any events for your application.
 *
 * @return void
 */
public function boot()
{
    parent::boot();

    Queue::looping(function (\Illuminate\Queue\Events\Looping $event) {
        if (('mail' == $event->queue) && (cache()->get('mail-queue-paused'))) {
            return false;
        }
    });
}

这假定您在应用程序中的其他位置具有确定何时暂停队列的机制,我通过检查缓存中是否存在特定键来演示了这一点。

答案 1 :(得分:2)

<?php

namespace App\Jobs;

use ...

class SendRequest implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    const REMOTE_SERVER_UNAVAILABLE = 'remote_server_unavailable';

    private $msg;
    private $retryAfter;

    public function __construct($msg)
    {
        $this->msg = $msg;
        $this->retryAfter = 10;
    }

    /**
    * Execute the job.
    *
    * @return void
    */
    public function handle(){
        try {
            // if we have tried sending the request and get a RemoteServerException, we will
            // redispatch the job directly and return.
            if(Cache::get(self::REMOTE_SERVER_UNAVAILABLE)) {
                self::dispatch($this->msg)->delay(Carbon::now()->addMinutes($this->retryAfter));
                return;                  
            }
            // send request to remote server
            // ...
        } catch (RemoteServerException $e) {
            // set a cache value expires in 10 mins if not exists.
            Cache::add(self::REMOTE_SERVER_UNAVAILABLE,'1', $this->retryAfter);
            // if the remote service undergoes a maintenance, redispatch a new delayed job.
            self::dispatch($this->msg)->delay(Carbon::now()->addMinutes($this->retryAfter));            
        }
    }
}