如何取消Laravel或Redis中的排队作业

Rya*_*yan 12 queue jobs delay redis laravel

如何浏览Redis队列中的所有待处理作业,以便取消具有某个emailAddress-sendTime对的Mailable?

我正在使用Laravel 5.5并拥有一个Mailable,我正在成功使用如下:

$sendTime = Carbon::now()->addHours(3);
Mail::to($emailAddress)
      ->bcc([config('mail.supportTeam.address'), config('mail.main.address')])
                    ->later($sendTime, new MyCustomMailable($subject, $dataForMailView));
Run Code Online (Sandbox Code Playgroud)

运行此代码时,作业将添加到我的Redis队列中.

我已经阅读过Laravel文档,但仍然感到困惑.

如何取消Mailable(阻止发送)?

我喜欢在我的Laravel应用程序中编写一个网页,这对我来说很容易.

或者也许有一些工具已经让这很容易(也许是FastoRedis?)?在这种情况下,关于如何以这种方式实现这一目标的说明也将非常有用.谢谢!

更新:

我尝试使用FastoRedis浏览Redis队列,但我无法弄清楚如何删除Mailable,例如红色箭头指向此处: 在此输入图像描述

更新:

请看下面我提供的综合答案.

San*_*r82 7

让它更容易.

请勿使用后面的选项发送电子邮件.您必须使用后面的选项发送作业,此作业将负责发送电子邮件.

在此作业中,在发送电子邮件之前,请检查emailAddress-sendTime对.如果是正确的,发送电子邮件,如果没有,则返回true,电子邮件将不会发送,作业将完成.


Ale*_*ldi 7

删除所有排队的作业:

Redis::command('flushdb');
Run Code Online (Sandbox Code Playgroud)

  • 这将刷新所有新邮件和挂起的邮件,无论是否应“取消”。 (3认同)

Rya*_*yan 5

综合回答:

我现在使用我自己的自定义 DispatchableWithControl 特征而不是 Dispatchable 特征。

我这样称呼它:

$executeAt = Carbon::now()->addDays(7)->addHours(2)->addMinutes(17);
SomeJobThatWillSendAnEmailOrDoWhatever::dispatch($contactId, $executeAt);
Run Code Online (Sandbox Code Playgroud)
namespace App\Jobs;

use App\Models\Tag;
use Carbon\Carbon;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Log;

class SomeJobThatWillSendAnEmailOrDoWhatever implements ShouldQueue {

    use DispatchableWithControl,
        InteractsWithQueue,
        Queueable,
        SerializesModels;

    protected $contactId;
    protected $executeAt;

    /**
     * 
     * @param string $contactId
     * @param Carbon $executeAt
     * @return void
     */
    public function __construct($contactId, $executeAt) {
        $this->contactId = $contactId;
        $this->executeAt = $executeAt;
    }

    /**
     * Execute the job. 
     *
     * @return void
     */
    public function handle() {
        if ($this->checkWhetherShouldExecute($this->contactId, $this->executeAt)) {
            //do stuff here
        }
    }

    /**
     * The job failed to process. 
     *
     * @param  Exception  $exception
     * @return void
     */
    public function failed(Exception $exception) {
        // Send user notification of failure, etc...
        Log::error(static::class . ' failed: ' . $exception);
    }

}
Run Code Online (Sandbox Code Playgroud)
namespace App\Jobs;

use App\Models\Automation;
use Carbon\Carbon;
use Illuminate\Foundation\Bus\PendingDispatch;
use Log;

trait DispatchableWithControl {

    use \Illuminate\Foundation\Bus\Dispatchable {///sf/ask/2820935631/
        \Illuminate\Foundation\Bus\Dispatchable::dispatch as parentDispatch;
    }

    /**
     * Dispatch the job with the given arguments.
     *
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public static function dispatch() {
        $args = func_get_args();
        if (count($args) < 2) {
            $args[] = Carbon::now(TT::UTC); //if $executeAt wasn't provided, use 'now' (no delay)
        }
        list($contactId, $executeAt) = $args;
        $newAutomationArray = [
            'contact_id' => $contactId,
            'job_class_name' => static::class,
            'execute_at' => $executeAt->format(TT::MYSQL_DATETIME_FORMAT)
        ];
        Log::debug(json_encode($newAutomationArray));
        Automation::create($newAutomationArray);
        $pendingDispatch = new PendingDispatch(new static(...$args));
        return $pendingDispatch->delay($executeAt);
    }

    /**
     * @param int $contactId
     * @param Carbon $executeAt
     * @return boolean
     */
    public function checkWhetherShouldExecute($contactId, $executeAt) {
        $conditionsToMatch = [
            'contact_id' => $contactId,
            'job_class_name' => static::class,
            'execute_at' => $executeAt->format(TT::MYSQL_DATETIME_FORMAT)
        ];
        Log::debug('checkWhetherShouldExecute ' . json_encode($conditionsToMatch));
        $automation = Automation::where($conditionsToMatch)->first();
        if ($automation) {
            $automation->delete();
            Log::debug('checkWhetherShouldExecute = true, so soft-deleted record.');
            return true;
        } else {
            return false;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

所以,现在我可以查看我的“自动化”表以查看待处理的作业,如果我想阻止作业执行,我可以删除(或软删除)任何这些记录。

  • 您已经扩展了一段框架代码并向其中添加了您自己的业务逻辑。它可以在你的工作类别中完成,并且无需将其添加到该特征中。您违反了 SOLID 的单一职责原则,并且您的代码无法在其他地方重用。 (3认同)
  • @farzan 我完全不明白你的评论。通过这种方式编写它,我 *AM* 能够在多个地方使用它。*我的许多*工作都使用此特征(我希望能够轻松取消的工作)。我有什么误解? (3认同)