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