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

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

问题描述

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

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

$sendTime = Carbon::now()->addHours(3);邮件::to($emailAddress)->密件抄送([配置('mail.supportTeam.address'),配置('mail.main.address')])->稍后($sendTime, new MyCustomMailable($subject, $dataForMailView));

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

我已经阅读了

更新:

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

解决方案

综合回答:

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

我这样称呼它:

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


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


命名空间 AppJobs;使用应用模型自动化;使用碳碳;使用 IlluminateFoundationBusPendingDispatch;使用日志;特征 DispatchableWithControl {使用 IlluminateFoundationBusDispatchable {//https://stackoverflow.com/questions/40299080/is-there-a-way-to-extend-trait-in-phpIlluminateFoundationBusDispatchable::dispatch 作为 parentDispatch;}/*** 使用给定的参数调度作业.** @return IlluminateFoundationBusPendingDispatch*/公共静态函数调度(){$args = func_get_args();if (count($args) < 2) {$args[] = Carbon::now(TT::UTC);//如果没有提供$executeAt,使用'now'(没有延迟)}列表($contactId,$executeAt)=$args;$newAutomationArray = ['contact_id' =>$contactId,'job_class_name' =>静态::类,'execute_at' =>$executeAt->格式(TT::MYSQL_DATETIME_FORMAT)];日志::调试(json_encode($newAutomationArray));自动化::create($newAutomationArray);$pendingDispatch = new PendingDispatch(new static(...$args));return $pendingDispatch->delay($executeAt);}/*** @param int $contactId* @param 碳 $executeAt* @return 布尔值*/公共函数 checkWhetherShouldExecute($contactId, $executeAt) {$conditionsToMatch = ['contact_id' =>$contactId,'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,所以软删除记录.');返回真;} 别的 {返回假;}}}

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

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天全站免登陆