簡體   English   中英

你如何暫停 Laravel 隊列

[英]How do you pause a Laravel queue

我有一個向遠程服務發送請求的隊列。 有時,這項服務需要進行維護。 當遇到這種情況時,我希望所有隊列任務在 10 分鍾內暫停並重試。 我該如何實施?

您可以使用Queue::looping()事件偵聽器來暫停整個隊列或連接(而不僅僅是單個作業類)。 與其他方法不同,這不會在隊列暫停時將每個作業置於彈出/重新排隊的循環中,這意味着嘗試次數不會增加

這是文檔所說的:

使用Queue Facade 上的looping方法,您可以指定在 worker 嘗試從隊列中獲取作業之前執行的回調。

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

並沒有很好地記錄的是,如果回調返回false那么工作人員將不會獲取另一個工作 例如,這將阻止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是否在列表中。

因此,例如,如果您想創建一個基本的斷路器來在您的郵件服務返回維護錯誤時暫停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 (($event->queue == 'mail') && (cache()->get('mail-queue-paused'))) {
            return false;
        }
    });
}

這假設您在應用程序的其他地方有一種機制來檢測適當的情況,在本例中,該機制需要為共享緩存中的mail-queue-paused分配一個值(因為這是我的代碼正在檢查的為)。 有更強大的解決方案,但在緩存中設置一個特定的眾所周知的鍵(並自動使其過期)很簡單並且可以達到預期的效果。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM