|
|
本帖最后由 追影 于 2025-6-26 09:15 编辑
大米cms7.x使用异步队列(数据库版)实现实例:
使用场景:有时我们需要点击某个按钮立刻响应, 但实际需要执行一个大的任务(耗时未知或很长)才会回调.这就需要用到异步队列
1:安装依赖:
- composer require topthink/think-queue
复制代码
2:配置队列为使用数据库
3:创建数据库迁移文件
- php think queue:table
- php think queue:failed-table
- php think migrate:run
复制代码 4:创建队列任务(队列里要做的任务)
- <?php
- namespace app\job;
- use app\base\service\FoodAi;
- use think\facade\Config;
- use think\facade\Log;
- use think\queue\Job;
- use app\base\model\Article as ArticleModel;
- use think\facade\Db;
- class PythonStudy
- {
- // 最大尝试次数(默认 3 次)
- public $tries = 2;
- // 最大异常次数(可选)
- public $maxExceptions = 2;
- public function fire(Job $job, $article) {
- // 处理任务逻辑
- try {
- //处理任务
- $this->do_upload($article);
- // 任务成功处理后删除
- $job->delete();
- } catch (\Exception $e) {
- // 任务失败处理
- $job->fail();
- }
- }
- public function failed($data) {
- // 任务失败回调
- echo "Job failed: " . json_encode($data) . "\n";
- Log::error('python学习任务失败', $data);
- }
- private function shouldUpload($article)
- {
- return $article->title
- && $article->aid
- && $article->ai_pictures
- && !$article->upload_ai
- && !$article->public_price
- && !$article->isflash;
- }
- private function do_upload($article_arr){
- try {
- $article = (object)$article_arr;//习惯用object
- if (!$this->shouldUpload($article)) {
- echo '验证参数不通过';
- return;
- }
- $str_pics = $article->ai_pictures;
- $company_code = $article->company_code?:$this->request->param('company_code');
- if(!$company_code) {echo('未传递company_code');return;}
- \payment\Common::changeDbByCompany($company_code);
- //上传数据集
- $baidu_service = new FoodAi();
- $r = $baidu_service->multi_study($str_pics, $article_arr,$company_code);
- if($r) {
- $article_model = new ArticleModel();
- $article_model->where('aid', '=', $article->aid)->save(['upload_ai' => 1]);
- echo 'python do upload success';
- }else{
- echo 'python do upload fail';
- }
- return true;
- }catch (\Exception $exception){
- echo $exception->getFile().$exception->getMessage();
- }
- return false;
- }
- }
复制代码
(5)写一个事件促发异步队列
- <?php
- namespace app\base\event;
- use app\base\service\Baidu as BaiduService;
- use think\facade\Log;
- use think\facade\Queue;
- class PythonAi
- {
- public function handle($article)
- {
- Queue::push(\app\job\PythonStudy::class,$article);
- }
- }
复制代码
(6)注册事件与触发该事件
注册全局事件 app/event.php
- <?php
- // 事件定义文件
- return [
- 'bind' => [
- ],
- 'listen' => [
- 'AppInit' => [],
- 'HttpRun' => [],
- 'HttpEnd' => [],
- 'LogLevel' => [],
- 'LogWrite' => [],
- 'AiStudy' => [
- \app\base\event\PythonAi::class,
- ],
- ],
- 'subscribe' => [
- ],
- ];
复制代码 触发事件:用内置的event函数即可
- private function do_event($article){
- $article->company_code = $this->get_company_code();
- $article_arr = $article->toArray();
- //var_dump($article_arr);
- //触发事件
- event('AiStudy',$article_arr);
- }
复制代码
(7)最后 计划任务 让队列跑起来
- # 以守护进程方式运行
- php think queue:work
复制代码
顺带说下centos守护进程方式运行supervisord配置如下
- [program:think-queue]
- command=php /wwwroot/hall/xunyuan/think queue:work
- directory=/wwwroot/hall/xunyuan
- autostart=true
- autorestart=true
- startretries=3
- user=nginx
- numprocs=1
- redirect_stderr=true
- stdout_logfile=/var/log/supervisor/think-queue.log
复制代码
|
|