作者 赵彬吉

update

@@ -9,11 +9,12 @@ use App\Helper\Translate; @@ -9,11 +9,12 @@ use App\Helper\Translate;
9 use App\Models\Ai\AiCommand; 9 use App\Models\Ai\AiCommand;
10 use App\Models\Mail\Mail; 10 use App\Models\Mail\Mail;
11 use App\Models\Project\DeployOptimize; 11 use App\Models\Project\DeployOptimize;
  12 +use App\Models\Project\ProjectUpdateTdk;
12 use App\Models\User\User; 13 use App\Models\User\User;
13 use App\Services\ProjectServer; 14 use App\Services\ProjectServer;
14 use Illuminate\Console\Command; 15 use Illuminate\Console\Command;
  16 +use Illuminate\Support\Facades\Cache;
15 use Illuminate\Support\Facades\DB; 17 use Illuminate\Support\Facades\DB;
16 -use Illuminate\Support\Facades\Redis;  
17 18
18 /** 19 /**
19 * 初始化项目 20 * 初始化项目
@@ -132,31 +133,30 @@ class UpdateSeoTdk extends Command @@ -132,31 +133,30 @@ class UpdateSeoTdk extends Command
132 public function handle() 133 public function handle()
133 { 134 {
134 while (true) { 135 while (true) {
135 - $project_id = Redis::rpop('updateSeoTdk'); 136 + $task = ProjectUpdateTdk::getPendingTask();
  137 + $project_id = $task->project_id;
136 if (!$project_id) { 138 if (!$project_id) {
137 - sleep(2); 139 + sleep(10);
138 continue; 140 continue;
139 } 141 }
140 echo date('Y-m-d H:i:s') . ' start project_id: ' . $project_id . PHP_EOL; 142 echo date('Y-m-d H:i:s') . ' start project_id: ' . $project_id . PHP_EOL;
141 try { 143 try {
142 ProjectServer::useProject($project_id); 144 ProjectServer::useProject($project_id);
143 - $this->seo_tdk($project_id); 145 + $this->seo_tdk($project_id, $task->id);
144 DB::disconnect('custom_mysql'); 146 DB::disconnect('custom_mysql');
145 }catch (\Exception $e){ 147 }catch (\Exception $e){
146 echo date('Y-m-d H:i:s') . 'line: '. $e->getLine() .' error: ' . $project_id . '->' . $e->getMessage() . PHP_EOL; 148 echo date('Y-m-d H:i:s') . 'line: '. $e->getLine() .' error: ' . $project_id . '->' . $e->getMessage() . PHP_EOL;
  149 + ProjectUpdateTdk::retry($task->id, $e->getMessage());
147 } 150 }
148 echo date('Y-m-d H:i:s') . ' end: ' . $project_id . PHP_EOL; 151 echo date('Y-m-d H:i:s') . ' end: ' . $project_id . PHP_EOL;
149 } 152 }
150 } 153 }
151 154
152 - public function seo_tdk($project_id) 155 + public function seo_tdk($project_id, $task_id)
153 { 156 {
154 - $data = [];  
155 - $update = [  
156 - 'created_at'=>date('Y-m-d H:i:s'),  
157 - 'updated_at'=>date('Y-m-d H:i:s'),  
158 - 'project_id'=>$project_id,  
159 - ];//更新统计 157 +
  158 + //更新统计
  159 + $update = [];
160 $ai_commands = AiCommand::where('is_batch', 1)->select('key', 'scene', 'ai')->get()->toArray(); 160 $ai_commands = AiCommand::where('is_batch', 1)->select('key', 'scene', 'ai')->get()->toArray();
161 $ai_commands = Arr::setValueToKey($ai_commands, 'key'); 161 $ai_commands = Arr::setValueToKey($ai_commands, 'key');
162 foreach ($this->maps as $table => $map) { 162 foreach ($this->maps as $table => $map) {
@@ -186,6 +186,15 @@ class UpdateSeoTdk extends Command @@ -186,6 +186,15 @@ class UpdateSeoTdk extends Command
186 echo $field.'已有值 跳过' . PHP_EOL; 186 echo $field.'已有值 跳过' . PHP_EOL;
187 continue; 187 continue;
188 } 188 }
  189 +
  190 + //缓存 在处理的 项目 数据 id
  191 + $cache_key = "seo_tdk_{$project_id}_{$table}_{$v['id']}";
  192 + if(Cache::get($cache_key)){
  193 + echo '其他进程在处理' . PHP_EOL;
  194 + continue;
  195 + }
  196 + Cache::put($cache_key, 1, 120);
  197 +
189 //AI生成 198 //AI生成
190 if (!empty($ai_commands[$ai_key]['ai'])) { 199 if (!empty($ai_commands[$ai_key]['ai'])) {
191 $prompt = $this->getPrompt($project_id, $ai_commands[$ai_key]['ai'], $table, $v); 200 $prompt = $this->getPrompt($project_id, $ai_commands[$ai_key]['ai'], $table, $v);
@@ -262,10 +271,9 @@ class UpdateSeoTdk extends Command @@ -262,10 +271,9 @@ class UpdateSeoTdk extends Command
262 } 271 }
263 DB::connection('custom_mysql')->table($table)->where(['id' => $v['id']])->update($data); 272 DB::connection('custom_mysql')->table($table)->where(['id' => $v['id']])->update($data);
264 } 273 }
265 - $update[$table] = json_encode($update[$table]);  
266 } 274 }
267 } 275 }
268 - DB::table('gl_project_update_tdk')->insert($update); 276 + ProjectUpdateTdk::finish($task_id, $update);
269 } 277 }
270 278
271 public function getPrompt($project_id, $prompt, $table, $data){ 279 public function getPrompt($project_id, $prompt, $table, $data){
@@ -151,6 +151,9 @@ class Arr extends \Illuminate\Support\Arr @@ -151,6 +151,9 @@ class Arr extends \Illuminate\Support\Arr
151 */ 151 */
152 public static function s2a($str) 152 public static function s2a($str)
153 { 153 {
  154 + if(!$str){
  155 + return [];
  156 + }
154 if (is_array($str)) { 157 if (is_array($str)) {
155 return $str; 158 return $str;
156 } 159 }
@@ -11,6 +11,7 @@ namespace App\Http\Controllers\Aside\Com; @@ -11,6 +11,7 @@ namespace App\Http\Controllers\Aside\Com;
11 11
12 use App\Helper\Common; 12 use App\Helper\Common;
13 use App\Http\Controllers\Bside\BaseController; 13 use App\Http\Controllers\Bside\BaseController;
  14 +use App\Models\Project\ProjectUpdateTdk;
14 use App\Services\ProjectServer; 15 use App\Services\ProjectServer;
15 use Illuminate\Support\Facades\DB; 16 use Illuminate\Support\Facades\DB;
16 use Illuminate\Support\Facades\Redis; 17 use Illuminate\Support\Facades\Redis;
@@ -37,7 +38,7 @@ class UpdateController extends BaseController @@ -37,7 +38,7 @@ class UpdateController extends BaseController
37 ],[ 38 ],[
38 'project_id.required' => 'project_id不能为空', 39 'project_id.required' => 'project_id不能为空',
39 ]); 40 ]);
40 - Redis::lpush('updateSeoTdk', $this->param['project_id']); 41 + ProjectUpdateTdk::add_task($this->param['project_id']);
41 $this->response('任务添加成功'); 42 $this->response('任务添加成功');
42 } 43 }
43 } 44 }
@@ -9,10 +9,104 @@ @@ -9,10 +9,104 @@
9 9
10 namespace App\Models\Project; 10 namespace App\Models\Project;
11 11
  12 +use App\Helper\Arr;
12 use App\Models\Base; 13 use App\Models\Base;
  14 +use Illuminate\Support\Facades\DB;
  15 +use Illuminate\Support\Facades\Log;
13 16
14 class ProjectUpdateTdk extends Base 17 class ProjectUpdateTdk extends Base
15 { 18 {
16 //设置关联表名 19 //设置关联表名
17 protected $table = 'gl_project_update_tdk'; 20 protected $table = 'gl_project_update_tdk';
  21 +
  22 + const STATUS_PENDING = 0;
  23 + const STATUS_SUCCESS = 1;
  24 + const STATUS_FAIL = 2;
  25 +
  26 + /**
  27 + * 新建任务
  28 + * @param $project_id
  29 + * @author zbj
  30 + * @date 2023/11/9
  31 + */
  32 + public static function add_task($project_id){
  33 + $model = new self();
  34 + $model->project_id = $project_id;
  35 + $model->save();
  36 + }
  37 +
  38 + /**
  39 + * 获取待处理任务
  40 + * @return mixed
  41 + * @author zbj
  42 + * @date 2023/11/9
  43 + */
  44 + public static function getPendingTask(){
  45 + return self::where('status', self::STATUS_PENDING)->orderBy('id', 'asc')->first();
  46 + }
  47 +
  48 + /**
  49 + * 重试任务
  50 + * @param $id
  51 + * @param $remark
  52 + * @author zbj
  53 + * @date 2023/11/9
  54 + */
  55 + public static function retry($id, $remark)
  56 + {
  57 + DB::beginTransaction();
  58 + try {
  59 + //行锁 避免脏读写
  60 + $data = self::where('id', $id)->lockForUpdate()->first();
  61 + $data->retry = $data->retry + 1;
  62 + if ($data->retry > 3) {
  63 + $data->status = self::STATUS_FAIL;
  64 + }else{
  65 + $data->status = self::STATUS_PENDING;
  66 + }
  67 + $data->remark = mb_substr($remark, 0, 250);
  68 + $data->save();
  69 +
  70 + DB::commit();
  71 + } catch (\Exception $e) {
  72 + DB::rollback();
  73 + Log::error('project_update_tdk retry error:' . $e->getMessage());
  74 + }
  75 + }
  76 +
  77 + /**
  78 + * 完成
  79 + * @param $id
  80 + * @param $update_data
  81 + * @author zbj
  82 + * @date 2023/11/9
  83 + */
  84 + public static function finish($id, $update_data){
  85 + DB::beginTransaction();
  86 + try {
  87 + //行锁 避免脏读写
  88 + $data = self::where('id', $id)->lockForUpdate()->first();
  89 + $data->status = self::STATUS_SUCCESS;
  90 +
  91 + foreach($update_data as $field => $item){
  92 + $old_date = Arr::s2a($data->$field);
  93 + $new_data = [];
  94 + foreach($item as $k=>$v){
  95 + if($k == 'total_page'){
  96 + $new_data[$k] = $v;
  97 + }else{
  98 + $new_data[$k] = $v + ($old_date[$k] ?? 0);
  99 + }
  100 + }
  101 + $data->$field = $new_data;
  102 + }
  103 +
  104 + $data->save();
  105 +
  106 + DB::commit();
  107 + } catch (\Exception $e) {
  108 + DB::rollback();
  109 + Log::error('project_update_tdk finish error:' . $e->getMessage());
  110 + }
  111 + }
18 } 112 }