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

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

问题描述

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

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

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

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

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

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

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

如何取消可邮寄邮件(阻止其发送)?

我很想在Laravel应用中编写一个网页,对我来说这很容易.

或者也许已经有一些工具可以简化此操作(也许是FastoRedis?)?在这种情况下,有关如何以这种方式实现此目标的说明也将非常有帮助.谢谢!

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!

更新:

我尝试使用FastoRedis浏览Redis队列,但是我不知道如何删除Mailable,例如红色箭头指向此处:

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:

请参阅下面我提供的全面的答案.

Look at the comprehensive answer I provided below.

推荐答案

全新,全面的答案:

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

New, Comprehensive Answer:

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

我这样称呼它:

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


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

}


namespace App\Jobs;

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

trait DispatchableWithControl {

    use \Illuminate\Foundation\Bus\Dispatchable {//https://stackoverflow.com/questions/40299080/is-there-a-way-to-extend-trait-in-php
        \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;
        }
    }

}

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

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.

我在服务器上设置了一个新应用,并在其自己的子域中安装了用于管理我的Redis的此Web界面:

I set up a new app on my server and installed (on its own subdomain) this web interface for managing my Redis: https://github.com/ErikDubbelboer/phpRedisAdmin

它允许我编辑或删除ZSet键和值,这似乎是Laravel延迟邮件的保存方式.

It allows me to edit or delete ZSet keys and values, which seems to be how Laravel delayed Mailables get saved to the queue.

对我有用的另一种方法是在Windows PC上安装 Redis Desktop Manager .

Another approach that worked for me was to install Redis Desktop Manager on my Windows PC.

我想我更喜欢phpRedisAdmin,因为我可以从网络(使用任何设备)访问它.

I think I'll prefer phpRedisAdmin since I'll be able to access it from the web (using any device).

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

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