如何取消 Laravel 或 Redis 中的排队作业 [英] How to cancel queued job in Laravel or Redis

查看:49
本文介绍了如何取消 Laravel 或 Redis 中的排队作业的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我正在使用 Laravel 5.5 并且有一个我成功使用的 Mailable,如下所示:

$sendTime = Carbon::now()->addHours(3);邮件::至($emailAddress)-> bcc([config('mail.supportTeam.address'), config('mail.main.address')])-> 稍后($sendTime, new MyCustomMailable($subject, $dataForMailView));

当这段代码运行时,一个作业被添加到我的 Redis 队列中.

我已经阅读了

更新:

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

解决方案

综合解答:

我现在使用我自己的自定义 DispatchableWithControl trait 而不是 Dispatchable trait.

我这样称呼它:

$executeAt = Carbon::now()->addDays(7)->addHours(2)->addMinutes(17);SomeJobThatWillSendAnEmailOrDoWhatever::dispatch($contactId, $executeAt);


命名空间 AppJobs;使用 AppModelsTag;使用碳碳;使用异常;使用 IlluminateBusQueueable;使用 IlluminateQueueSerializesModels;使用 IlluminateQueueInteractsWithQueue;使用 IlluminateContractsQueueShouldQueue;使用日志;类 SomeJobThatWillSendAnEmailOrDoWhatever 实现了 ShouldQueue {使用 DispatchableWithControl,与队列交互,排队,序列化模型;受保护的 $contactId;受保护的 $executeAt;/**** @param string $contactId* @param Carbon $executeAt* @return 无效*/公共函数 __construct($contactId, $executeAt) {$this->contactId = $contactId;$this->executeAt = $executeAt;}/*** 执行作业.** @return 无效*/公共函数句柄(){如果 ($this->checkWhetherShouldExecute($this->contactId, $this->executeAt)) {//在这里做事}}/*** 作业无法处理.** @param 异常 $exception* @return 无效*/公共函数失败(异常 $exception){//向用户发送失败通知等...Log::error(static::class . ' failed: ' . $exception);}}


命名空间 AppJobs;使用 AppModelsAutomation;使用碳碳;使用 IlluminateFoundationBusPendingDispatch;使用日志;特质 DispatchableWithControl {使用 IlluminateFoundationBusDispatchable {//https://stackoverflow.com/questions/40299080/is-there-a-way-to-extend-trait-in-phpIlluminateFoundationBusDispatchable::dispatch as parentDispatch;}/*** 使用给定的参数调度作业.** @return IlluminateFoundationBusPendingDispatch*/公共静态函数调度(){$args = func_get_args();如果(计数($args)<2){$args[] = Carbon::now(TT::UTC);//如果没有提供$executeAt,使用'now'(无延迟)}list($contactId, $executeAt) = $args;$newAutomationArray = ['contact_id' =>$联系人ID,'job_class_name' =>静态::类,'execute_at' =>$executeAt-> 格式(TT::MYSQL_DATETIME_FORMAT)];日志::调试(json_encode($newAutomationArray));自动化::创建($newAutomationArray);$pendingDispatch = new PendingDispatch(new static(...$args));返回 $pendingDispatch->delay($executeAt);}/*** @param int $contactId* @param Carbon $executeAt* @return 布尔值*/公共函数 checkWhetherShouldExecute($contactId, $executeAt) {$conditionsToMatch = ['contact_id' =>$联系人ID,'job_class_name' =>静态::类,'execute_at' =>$executeAt-> 格式(TT::MYSQL_DATETIME_FORMAT)];Log::debug('checkWhetherShouldExecute' .json_encode($conditionsToMatch));$automation = Automation::where($conditionsToMatch)->first();如果($自动化){$automation->delete();Log::debug('checkWhetherShouldExecute = true, so soft-deleted record.');返回真;} 别的 {返回假;}}}

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

How can I browse all the pending jobs within my Redis queue so that I could cancel the Mailable that has a certain emailAddress-sendTime pair?

I'm using Laravel 5.5 and have a Mailable that I'm using successfully as follows:

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

When this code runs, a job gets added to my Redis queue.

I've already read the Laravel docs but remain confused.

How can I cancel a Mailable (prevent it from sending)?

I'd love to code a webpage within my Laravel app that makes this easy for me.

Or maybe there are tools that already make this easy (maybe FastoRedis?)? In that case, instructions about how to achieve this goal that way would also be really helpful. Thanks!

Update:

I've tried browsing the Redis queue using FastoRedis, but I can't figure out how to delete a Mailable, such as the red arrow points to here:

UPDATE:

Look at the comprehensive answer I provided below.

解决方案

Comprehensive Answer:

I now use my own custom DispatchableWithControl trait instead of the Dispatchable trait.

I call it like this:

$executeAt = Carbon::now()->addDays(7)->addHours(2)->addMinutes(17);
SomeJobThatWillSendAnEmailOrDoWhatever::dispatch($contactId, $executeAt);


namespace AppJobs;

use AppModelsTag;
use CarbonCarbon;
use Exception;
use IlluminateBusQueueable;
use IlluminateQueueSerializesModels;
use IlluminateQueueInteractsWithQueue;
use IlluminateContractsQueueShouldQueue;
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);
    }

}


namespace AppJobs;

use AppModelsAutomation;
use CarbonCarbon;
use IlluminateFoundationBusPendingDispatch;
use Log;

trait DispatchableWithControl {

    use IlluminateFoundationBusDispatchable {//https://stackoverflow.com/questions/40299080/is-there-a-way-to-extend-trait-in-php
        IlluminateFoundationBusDispatchable::dispatch as parentDispatch;
    }

    /**
     * Dispatch the job with the given arguments.
     *
     * @return IlluminateFoundationBusPendingDispatch
     */
    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;
        }
    }

}

So, now I can look in my 'automations' table to see pending jobs, and I can delete (or soft-delete) any of those records if I want to prevent the job from executing.

这篇关于如何取消 Laravel 或 Redis 中的排队作业的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆