php 3600环形定时队列

<?php
//2021-07-13 13:42:27
namespace app\user\service;

use think\cache\driver\Redis;
use think\Db;
use think\Config;
use think\Log;

class CrondService
{
    private $redis;
    private $key;
    private $config;
    public function __construct()
    {
        $this->key = 'crond';
        $this->config = config('queue');
    }

    public function redis(){
        if (empty($this->redis)) {
            $con = new Redis($this->config);
            $this->redis = $con->handler();
        }
        return $this->redis;
    }

    public function generateData(){
        $exist = $this->redis()->exists($this->key);
        if(!$exist){
            for($i=1;$i<=3600;$i++){
                $single_key = 'solt_'.$i;
                $this->redis()->rpush($this->key,$single_key);
            }
        }else{
            //$this->redis()->delete($this->key);
//            $info = $this->redis()->lrange($this->key,0,-1);
//            print_r($info);die;
        }
    }
    public function addcrond($jobinfo,$time){
        $exist = $this->redis()->exists($this->key);
        if(!$exist){
            $this->generateData();
        }
        !is_numeric($time) && $time = strtotime($time);
        if($time<time()) return false;
        $cycle_num = ceil(($time - time())/3600);
        $single_key = 'solt_'.(($time - time())%3600);
        $jobinfo['cycle_num'] = $cycle_num;
        $rs = $this->redis()->sadd($single_key,serialize($jobinfo));
        return $rs;
    }

    public function docrond(){
        //取出当前任务组节点
        $nowjobs_name = $this->redis()->lpop($this->key);
        //将当前任务节点移动最后
        $this->redis()->rpush($this->key,$nowjobs_name);
        //取出当前任务组所有任务
        $nowjobs = $this->redis()->smembers($nowjobs_name);
        if($nowjobs){
            //$this->redis()->delete($nowjobs_name);
            $dojobs = $leftjobs = [];
            if($nowjobs){
                foreach ($nowjobs as $k=>&$v){
                    $v = unserialize($v);
                    //任务圈数减1
                    $v['cycle_num'] = $v['cycle_num'] -1;
                    if($v['cycle_num']<1){
                        $dojobs[] = $v;
                        unset($nowjobs[$k]);
                    }
                }
                unset($v);
                //需要执行的任务
                if($dojobs){
                    //队列执行
                    foreach ($dojobs as $job){
                        //写入队列执行操作
                        $jobname = $job['job'];
                        unset($job['job']);
                        queue_push('app\common\queue\\'.$jobname, $job, $jobname);
                    }
                    if($nowjobs){
                        $leftjobs = array_map(function ($tv){
                            $tv = serialize($tv);
                            return $tv;
                        },$nowjobs);
                        $this->redis()->sadd($nowjobs_name,...$leftjobs);
                        return true;
                    }
                    return true;
                }
            }else{
                return true;
            }
        }else{
            return true;
        }
    }




}

  

    public function test(){
        $sv = new \app\user\service\CrondService();
        for($i=0;$i<=86400;$i++){
            $time = time()+$i;
            $jobinfo = [
                'job'=>'OrderQueue',
                'fun'=>'closeOrder',//订单关闭
                'param'=>['orderid'=>rand(1,3600)],
            ];
            $data = $sv->addcrond($jobinfo,$time);
        }
        print_r($data);
    }

  

<?php

/**
 * usefor:订单任务
 * User: 骆云飞
 * Date: 2021/09/13
 */

namespace app\common\queue;

use app\api\service\OrderService;
use think\Log;
use think\queue\Job;

class OrderQueue
{
    /**
     * 用户日志入库
     * @param array $data  内容
     * @return
     */
    public function fire(Job $job, $data)
    {
        set_time_limit(0);
        $isJobDone = $this->send($data);
        if ($isJobDone) {
            //成功删除任务
            $job->delete();
        } else {
            //$job->release(3);
            $job->release(300 * $job->attempts());
        }
    }


    /**
     * 根据消息中的数据进行实际的业务处理
     * @param array|mixed    $data     发布任务时自定义的数据
     * @return boolean                 任务执行的结果
     */
    public function send($data)
    {
        $errorstr = "";
        try {
            $fun = array_saft_value($data, 'fun');
            if (empty($fun)) {
                return true;
            }
            try {
                return call_user_func([$this,$fun],$data);
            } catch (\Exception $ex) {
                Log::error($ex);
            }

        } catch (\Exception $e) {
            Log::error($e);
            $errorstr .= $e->getMessage();
        } finally {
        }

        return true;
    }

    public function closeOrder($data){
        $id = array_saft_value($data, 'orderid');
        if (empty($id)) {
            return true;
        }
        $sv = new OrderService();
        $where = [];
        $where['id'] = ['=',$id];
        $where['ispay'] = ['=',0];
        $where['status'] = ['=',0];
        $where['addtime'] = ['<=',time()-3600];
        $m = $sv->Get($where);
        if (empty($m)) {
            return true;
        }
        return $sv->Update(['status'=>-1],$where);
    }



}

  

posted @ 2022-01-07 14:42  飞鹰之歌  阅读(8)  评论(0)    收藏  举报