Laravel 延迟任务(Delayed Job)功能

当我们的系统触发了一个延迟任务,Laravel会用当前的时间加上任务的延迟时间计算出任务的执行时间戳,然后将这个时间戳和任务信息序列化之后存入队列,,Laravel 的队列处理器会不断查询并执行队列中满足预计执行时间等于或早于当前时间的任务。

1. 创建任务

我们通过 make:job 命令来创建一个任务:

 php artian make:job CloseOrder复制代码

创建的任务类保存在 app/Jobs 目录下,现在编辑刚刚创建的任务类:

app/Jobs/CloseOrder.php

$order;

    public function __construct(Order $order, $delay)
    {
        $this->order = $order;
        // 设置延迟的时间,delay() 方法的参数代表多少秒之后执行
        $this->delay($delay);
    }

    // 定义这个任务类具体的执行逻辑
    // 当队列处理器从队列中取出任务时,会调用 handle() 方法
    public function handle()
    {
        // 判断对应的订单是否已经被支付
        // 如果已经支付则不需要关闭订单,直接退出
        if ($this->order->paid_at) {
            return;
        }
        // 通过事务执行 sql
        \DB::transaction(function() {
            // 将订单的 closed 字段标记为 true,即关闭订单
            $this->order->update(['closed' => true]);
            // 循环遍历订单中的商品 SKU,将订单中的数量加回到 SKU 的库存中去
            foreach ($this->order->items as $item) {
                $item->productSku->addStock($item->amount);
            }
        });
    }
}复制代码


2. 触发任务

接下来我们需要在创建订单之后触发这个任务:

app/Http/Controllers/OrdersController.php

use App\Jobs\CloseOrder;
    .
    .
    .
    public function store(Request $request)
    {
        .
        .
        .
        $this->dispatch(new CloseOrder($order, config('app.order_ttl')));

        return $order;
    }复制代码

CloseOrder 构造函数的第二个参数延迟时间我们从配置文件中读取,为了方便我们测试,把这个值设置成 30 秒

'order_ttl' => 30,复制代码

3. 测试

默认情况下,Laravel 生成的 .env 文件里把队列的驱动设置成了 sync(同步),在同步模式下延迟任务会被立即执行,所以需要先把队列的驱动改成 redis

.env

.
.
.
QUEUE_CONNECTION=redis
.
.
.复制代码

要使用 redis 作为队列驱动,我们还需要引入 predis/predis 这个包

composer require predis/predis复制代码

接下来启动队列处理器:

php artisan queue:work复制代码

切记:如果测试中途要修改定时任务执行程序的内容,必须先停止队列,更改完事后重启队列。


转载于:https://juejin.im/post/5cac7947e51d456e361ed8a6

你可能感兴趣的:(Laravel 延迟任务(Delayed Job)功能)