作者 刘锟

Merge remote-tracking branch 'origin/master' into akun

@@ -42,11 +42,14 @@ class GeoWritingsTask extends Command @@ -42,11 +42,14 @@ class GeoWritingsTask extends Command
42 continue; 42 continue;
43 } 43 }
44 echo date("Y-m-d H:i:s").',执行的任务id'.$task_id.PHP_EOL; 44 echo date("Y-m-d H:i:s").',执行的任务id'.$task_id.PHP_EOL;
45 - $info = $geoWritingsTaskModel->read(['id'=>$task_id]); 45 + $info = $geoWritingsTaskModel->read(['id'=>$task_id,'status'=>1]);
46 if($info === false){ 46 if($info === false){
47 - echo date("Y-m-d H:i:s").',任务id数据不存在:'.$task_id.PHP_EOL; 47 + echo date("Y-m-d H:i:s").',任务id数据不存在/或已被执行:'.$task_id.PHP_EOL;
48 continue; 48 continue;
49 } 49 }
  50 + //修改状态为生成中
  51 + $geoWritingsModel = new GeoWritings();
  52 + $geoWritingsModel->edit(['status'=>$geoWritingsModel::STATUS_AI_RUNNING],['id'=>$info['writings_id']]);
50 //生成引言 53 //生成引言
51 $aiCommand1 = "请根据这个文章标题:{$info['title']},并同时参考公司的介绍’{$info['description']}‘以及公司参与的事件内容’{$info['event_content']}‘,给我写一个英文Press Release前言内容,前言内容请参考并引用{$info['keyword']}行业的一些专业数据报告,只需要1个段落,大约150-200字,请一定要出现这个关键词“{$info['prefix']}{$info['keyword']}{$info['suffix']}”,所有内容一定要用英文, 只需要回复我引言内容,不需要别的内容(比如序号、你的提示、寒暄、解释、注释之类的)"; 54 $aiCommand1 = "请根据这个文章标题:{$info['title']},并同时参考公司的介绍’{$info['description']}‘以及公司参与的事件内容’{$info['event_content']}‘,给我写一个英文Press Release前言内容,前言内容请参考并引用{$info['keyword']}行业的一些专业数据报告,只需要1个段落,大约150-200字,请一定要出现这个关键词“{$info['prefix']}{$info['keyword']}{$info['suffix']}”,所有内容一定要用英文, 只需要回复我引言内容,不需要别的内容(比如序号、你的提示、寒暄、解释、注释之类的)";
52 $gptHelper = new Gpt(); 55 $gptHelper = new Gpt();
@@ -57,21 +60,17 @@ class GeoWritingsTask extends Command @@ -57,21 +60,17 @@ class GeoWritingsTask extends Command
57 $images = explode(',',$info['img']); 60 $images = explode(',',$info['img']);
58 //组装一条数据 61 //组装一条数据
59 try { 62 try {
60 - $geoWritingsModel = new GeoWritings();  
61 $saveData = [ 63 $saveData = [
62 - 'project_id'=>$info['project_id'],  
63 - 'type'=>$geoWritingsModel::TYPE_AI_CREATE,  
64 'title'=>$info['title'], 64 'title'=>$info['title'],
65 'content'=>$introduction.($images[0] ?? '').PHP_EOL.$main.($images[1] ?? ''), 65 'content'=>$introduction.($images[0] ?? '').PHP_EOL.$main.($images[1] ?? ''),
66 'content_length'=>strlen($introduction.PHP_EOL.$main), 66 'content_length'=>strlen($introduction.PHP_EOL.$main),
67 - 'uniqid'=>md5(uniqid().$task_id.$info['project_id']), 67 + 'status'=>$geoWritingsModel::STATUS_INIT
68 ]; 68 ];
69 - $id = $geoWritingsModel->addReturnId($saveData); 69 + $geoWritingsModel->edit($saveData,['id'=>$info['writings_id']]);
70 $data = [ 70 $data = [
71 'introduction'=>$introduction, 71 'introduction'=>$introduction,
72 'main'=>$main, 72 'main'=>$main,
73 'status'=>2, 73 'status'=>2,
74 - 'writings_id'=>$id,  
75 ]; 74 ];
76 $geoWritingsTaskModel->edit($data,['id'=>$task_id]); 75 $geoWritingsTaskModel->edit($data,['id'=>$task_id]);
77 }catch (\Exception $e){ 76 }catch (\Exception $e){
@@ -88,20 +87,34 @@ class GeoWritingsTask extends Command @@ -88,20 +87,34 @@ class GeoWritingsTask extends Command
88 * @method :post 87 * @method :post
89 * @time :2025/10/27 14:22 88 * @time :2025/10/27 14:22
90 */ 89 */
91 - public function getTaskId(){ 90 + public function getTaskId()
  91 + {
92 $task_id = Redis::rpop('geo_writings_task'); 92 $task_id = Redis::rpop('geo_writings_task');
93 - $geoWritingsTaskModel = new GeoWritingsTaskModel(); 93 + // 如果队列空了,尝试补充
94 if (empty($task_id)) { 94 if (empty($task_id)) {
95 - $ids = $geoWritingsTaskModel->formatQuery(['status'=>0])->limit(100)->pluck('id');  
96 - if(!empty($ids)){  
97 - foreach ($ids as $id) {  
98 - Redis::lpush('geo_writings_task', $id); 95 + $lock_key = 'geo_writings_task_lock';
  96 + $lock_ttl = 10; // 锁过期时间10秒,防止死锁
  97 + $lock = Redis::set($lock_key, 1, 'EX', $lock_ttl, 'NX');
  98 + if ($lock) {
  99 + try {
  100 + $geoWritingsTaskModel = new GeoWritingsTaskModel();
  101 + $ids = $geoWritingsTaskModel->formatQuery(['status' => 0])->limit(100)->pluck('id');
  102 + if (!$ids->isEmpty()) {
  103 + // 标记这批任务为“生成中”
  104 + $geoWritingsTaskModel->edit(['status' => 1], ['id' => ['in', $ids]]);
  105 + foreach ($ids as $id) {
  106 + Redis::lpush('geo_writings_task', $id);
  107 + }
  108 + }
  109 + } finally {
  110 + // 释放锁
  111 + Redis::del($lock_key);
99 } 112 }
  113 + // 再次从队列中取任务
100 $task_id = Redis::rpop('geo_writings_task'); 114 $task_id = Redis::rpop('geo_writings_task');
101 } 115 }
102 - }else{  
103 - $geoWritingsTaskModel->edit(['status'=>1],['id'=>$task_id]);  
104 } 116 }
105 return $task_id; 117 return $task_id;
106 } 118 }
  119 +
107 } 120 }
@@ -116,7 +116,7 @@ class SyncProject extends Command @@ -116,7 +116,7 @@ class SyncProject extends Command
116 } 116 }
117 $item->status = NoticeLog::STATUS_SUCCESS; 117 $item->status = NoticeLog::STATUS_SUCCESS;
118 $item->save(); 118 $item->save();
119 - echo 'success:' . $item['id'] . '执行时间:' . date('Y-m-d H:i:s') . PHP_EOL; 119 + echo 'success:' . $item['id'] . '执行时间:'. 'ordet_id:'. $order_id . date('Y-m-d H:i:s') . PHP_EOL;
120 }catch (\Exception $e){ 120 }catch (\Exception $e){
121 echo 'error:' . $item['id'] . $e->getMessage() .' line ' . $e->getLine() . '执行时间:' . PHP_EOL; 121 echo 'error:' . $item['id'] . $e->getMessage() .' line ' . $e->getLine() . '执行时间:' . PHP_EOL;
122 errorLog('项目同步失败', $item, $e); 122 errorLog('项目同步失败', $item, $e);
@@ -49,6 +49,11 @@ class GeoWritingsTaskLogic extends BaseLogic @@ -49,6 +49,11 @@ class GeoWritingsTaskLogic extends BaseLogic
49 $id = $this->param['id']; 49 $id = $this->param['id'];
50 $this->model->edit($this->param,['id'=>$id]); 50 $this->model->edit($this->param,['id'=>$id]);
51 }else{ 51 }else{
  52 + //自动保存一条数据
  53 + $writingModel = new GeoWritings();
  54 + $this->param['writings_id'] = $writingModel->addReturnId(['project_id'=>$this->param['project_id'],
  55 + 'type'=>$writingModel::TYPE_AI_CREATE,'status'=>$writingModel::STATUS_AI_WAIT,
  56 + 'uniqid'=>md5(uniqid().rand(1, 99999).$this->param['project_id'])]);
52 $id = $this->model->addReturnId($this->param); 57 $id = $this->model->addReturnId($this->param);
53 } 58 }
54 }catch (\Exception $e){ 59 }catch (\Exception $e){