Laravel 延迟队列

场景示例:发布一篇文章或者任务,设定了上架时间,那么当上架时间到的时候,自动改变文章状态

思路:使用laravel延迟队列

Demo:文章状态改变(可直接复制代码运行)

1.准备:

  1. 使用Redis做队列驱动 ,开启Redis-server redis.conf
  2. 创建任务文件php artisan make:job endTask

2.编码:

web.php 路由

Route::get('/index', 'PostController@index');
Route::post('/posts', 'PostController@store');

PostController

    public function index()
    {
        return view('index');
    }

    public function store(Request $request)
    {
        $request->validate([
            'title'=>'required',
            'body'=> 'required',
        ]);
        $post['title'] = $request->title;
        $post['body'] = $request->body;
        $post['beginTime'] = Carbon::now()->addMinutes(1);
        $resPost = Post::create($post);

        //延时队列 更新文章状态
        endTask::dispatch($resPost)->delay($resPost->beginTime);
        return redirect()->back()->with('status', 'Your post has been submitted successfully');
    }

Post.php 模型文件

class Post extends Model
{
    //
    protected $table = 'posts';
    protected $fillable = ['title','body','beginTime','endTime'];
}

inde.blade.php 表单

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width">
    <title>Laravel Queues</title>
    <meta name="description" content="">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
</head>

<body>
<div class="container">
    <div class="col-md-5">
        <h4 class="page-header">Laravel Queues </h4>
        @foreach ($errors->all() as $error)
            <p class="alert alert-danger">{{ $error }}</p>
        @endforeach
        @if (session('status'))
            <div class="alert alert-success">
                {{ session('status')}}
            </div>
        @endif
        <form class="form-vertical" role="form" method="post" action="/posts">
            {{csrf_field()}}
            <div class="form-group">
                <input type="text" name="title" class="form-control" placeholder="Title">
            </div>
            <div class="form-group">
                <textarea class="form-control" rows="5" name="body" class="form-control" placeholder="Content"></textarea>
            </div>
            <div class="form-group">
                <button type="submit" class="btn btn-info">Submit Post</button>
            </div>
        </form>
    </div>
</div>
</body>
</html>

endTask队列

    public $post ;
    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(Post $post)
    {
        //
        $this->post = $post;
        Log::info('post handel postId __construct: '.$this->post->id);
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $res = Post::where('id',$this->post->id)->update(['status'=>2]); //更新文章的状态
        Log::info('post handel '.$this->post->id.'-status:'.$res);
    }

3.监听队列:

php artisan queue:work --daemon
遇到的坑:

一开始使用php artisan queue:work,取不到数据,后来换listen就可以了,主要是work是运行单次,对延迟队列不适用,查资料后使用了queue:work --daemon,这是三种队列启动监听的区别分析

坚持开源,坚持分享:)(bestcyt)

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 4

如果dispatch了一条delay任务,使用redis做driver,期间redis挂掉了,后面redis再重启,之前delay的消息是怎么处理的?大佬有研究吗,我试验了下是直接丢掉了。

3年前 评论

@purelightme 这个跟你redis的是否有开启持久化有关,如果你都没开持久化,肯定重启数据都队列。不管是不是延迟队列

3年前 评论

{--daemon : Run the worker in daemon mode (Deprecated)} 不是已经不建议所用了嘛

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!