visuddhinanda пре 2 месеци
родитељ
комит
fa0a27231c

+ 48 - 0
api-v12/app/Jobs/AiTranslate.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace App\Jobs;
+
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldBeUnique;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use App\Services\AiTranslateService;
+use Illuminate\Support\Facades\Log;
+
+class AiTranslate implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    public $tries = 3;       // 最大尝试次数(重试次数 = 3 - 1)
+    public $timeout = 60;    // 超时时间,单位:秒
+    private $aiService;
+    private $data;
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     */
+    public function __construct($data)
+    {
+        //
+        $this->data = $data;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        //
+        Log::info('AI translate job started', [
+            'message_id' => $this->data['message_id'] ?? null,
+        ]);
+        $data = json_decode(json_encode($this->data['payload']));
+        $this->aiService = app(AiTranslateService::class);
+        return $this->aiService->processTranslate($this->data['message_id'], $data, null);
+    }
+}

+ 118 - 0
api-v12/app/Jobs/BaseRabbitMQJob.php

@@ -0,0 +1,118 @@
+<?php
+
+namespace App\Jobs;
+
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Config;
+use App\Exceptions\TaskFailException;
+
+abstract class BaseRabbitMQJob implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    protected $queueName;
+    protected $messageData;
+    protected $currentRetryCount = 0;
+    protected $tries = 0;
+    protected $timeout = 0;
+    protected $messageId = null;
+    protected $stop = false;
+
+    public function __construct(string $queueName, string $messageId, array $messageData, int $retryCount = 0)
+    {
+        $this->queueName = $queueName;
+        $this->messageData = $messageData;
+        $this->currentRetryCount = $retryCount;
+        $this->messageId = $messageId;
+
+        // 从配置读取重试次数和超时时间
+        $queueConfig = config("mint.rabbitmq.queues.{$queueName}");
+        $this->tries = $queueConfig['retry_times'] ?? 3;
+        $this->timeout = $queueConfig['timeout'] ?? 300;
+    }
+
+    public function handle()
+    {
+        try {
+            Log::info("开始处理队列消息", [
+                'queue' => $this->queueName,
+                'message_id' => $this->messageId ?? 'unknown',
+                'retry_count' => $this->currentRetryCount
+            ]);
+
+            // 调用子类的具体业务逻辑
+            $result = $this->processMessage($this->messageData);
+
+            Log::info("队列消息处理完成", [
+                'queue' => $this->queueName,
+                'message_id' => $this->messageId ?? 'unknown',
+                'result' => $result
+            ]);
+
+            return $result;
+        } catch (TaskFailException $e) {
+            $this->handleFinalFailure($this->messageData, $e);
+            throw $e;
+        } catch (\Exception $e) {
+            Log::error("队列消息处理失败", [
+                'queue' => $this->queueName,
+                'message_id' => $this->messageId ?? 'unknown',
+                'error' => $e->getMessage(),
+                'retry_count' => $this->currentRetryCount,
+                'max_retries' => $this->tries
+            ]);
+
+            // 如果达到最大重试次数,处理失败逻辑
+            if ($this->currentRetryCount >= $this->tries - 1) {
+                $this->handleFinalFailure($this->messageData, $e);
+            }
+
+            throw $e; // 重新抛出异常以触发重试
+        }
+    }
+
+    public function failed(\Exception $exception)
+    {
+        Log::error("队列消息最终失败", [
+            'queue' => $this->queueName,
+            'message_id' => $this->messageId ?? 'unknown',
+            'error' => $exception->getMessage(),
+            'retry_count' => $this->currentRetryCount
+        ]);
+
+        // 发送到死信队列的逻辑将在 Worker 中处理
+    }
+
+    // 子类需要实现的具体业务逻辑
+    abstract protected function processMessage(array $messageData);
+
+    // 子类可以重写的失败处理逻辑
+    protected function handleFinalFailure(array $messageData, \Exception $exception)
+    {
+        // 默认实现:记录日志
+        Log::error("消息处理最终失败,准备发送到死信队列", [
+            'queue' => $this->queueName,
+            'message_id' => $this->messageId ?? 'unknown',
+            'error' => $exception->getMessage()
+        ]);
+    }
+
+    public function getQueueName(): string
+    {
+        return $this->queueName;
+    }
+
+    public function getCurrentRetryCount(): int
+    {
+        return $this->currentRetryCount;
+    }
+    public function stop()
+    {
+        $this->stop = true;
+    }
+}

+ 56 - 0
api-v12/app/Jobs/ProcessAITranslateJob.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Services\AiTranslateService;
+use App\Services\RabbitMQService;
+use Illuminate\Support\Facades\Log;
+use App\Exceptions\TaskFailException;
+use App\Tools\RedisClusters;
+
+class ProcessAITranslateJob extends BaseRabbitMQJob
+{
+    private $aiService;
+
+    protected function processMessage(array $messageData)
+    {
+        $startTime = microtime(true);
+        try {
+            // Laravel会自动注入
+            $this->aiService = app(AiTranslateService::class);
+            return $this->aiService->processTranslate($this->messageId, $messageData);
+        } catch (TaskFailException $e) {
+            throw $e;
+        } catch (\Exception $e) {
+            // 记录失败指标
+            throw $e;
+        } finally {
+            // 记录处理时间
+            $processingTime = microtime(true) - $startTime;
+            Log::info('翻译处理耗时', ['time' => $processingTime]);
+        }
+    }
+
+    protected function handleFinalFailure(array $messageData, \Exception $exception)
+    {
+        parent::handleFinalFailure($messageData, $exception);
+
+        // 消息处理最终失败,准备发送到死信队列
+        $this->aiService->handleFailedTranslate($this->messageId, $messageData, $exception);
+    }
+    public function stop()
+    {
+        parent::stop();
+        $this->aiService->stop();
+    }
+
+    public static function publish(string $taskId, $aiAssistantId): string
+    {
+        $data = AiTranslateService::makeByTask($taskId, $aiAssistantId);
+        $mq = app(RabbitMQService::class);
+        $queue = 'ai_translate_v2';
+        $msgId = $mq->publishMessage($queue, []);
+        RedisClusters::put("/mq/message/{$msgId}/data", $data);
+        return $msgId;
+    }
+}