ProcessBatchEpisodeGenerationJob.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. namespace App\Jobs;
  3. use Illuminate\Bus\Queueable;
  4. use Illuminate\Contracts\Queue\ShouldQueue;
  5. use Illuminate\Foundation\Bus\Dispatchable;
  6. use Illuminate\Queue\InteractsWithQueue;
  7. use Illuminate\Queue\SerializesModels;
  8. use Illuminate\Support\Facades\DB;
  9. use App\Services\DeepSeek\DeepSeekService;
  10. use App\Facade\Site;
  11. /**
  12. * 批量生成分集任务队列
  13. */
  14. class ProcessBatchEpisodeGenerationJob implements ShouldQueue
  15. {
  16. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  17. protected $taskId;
  18. protected $animeId;
  19. protected $startEpisodeNumber;
  20. protected $totalEpisodes;
  21. protected $requestData;
  22. protected $uid;
  23. protected $cpid;
  24. /**
  25. * 任务最大尝试次数
  26. */
  27. public $tries = 3;
  28. /**
  29. * 任务超时时间(秒)
  30. */
  31. public $timeout = 1800;
  32. /**
  33. * Create a new job instance.
  34. *
  35. * @param int $taskId 批量任务ID
  36. * @param int $animeId 动漫ID
  37. * @param int $startEpisodeNumber 起始集数
  38. * @param int $totalEpisodes 总共生成集数
  39. * @param array $requestData 请求数据
  40. * @param int $uid 用户ID
  41. * @param int $cpid 公司ID
  42. */
  43. public function __construct($taskId, $animeId, $startEpisodeNumber, $totalEpisodes, $requestData, $uid, $cpid)
  44. {
  45. $this->taskId = $taskId;
  46. $this->animeId = $animeId;
  47. $this->startEpisodeNumber = $startEpisodeNumber;
  48. $this->totalEpisodes = $totalEpisodes;
  49. $this->requestData = $requestData;
  50. $this->uid = $uid;
  51. $this->cpid = $cpid;
  52. }
  53. /**
  54. * Execute the job.
  55. *
  56. * @return void
  57. */
  58. public function handle()
  59. {
  60. try {
  61. // 设置当前用户上下文
  62. Site::setUid($this->uid);
  63. Site::setCpid($this->cpid);
  64. $deepSeekService = app(DeepSeekService::class);
  65. // 逐集生成
  66. for ($i = 0; $i < $this->totalEpisodes; $i++) {
  67. $currentEpisodeNumber = $this->startEpisodeNumber + $i;
  68. // 更新当前任务进度
  69. $this->updateTaskProgress($currentEpisodeNumber, 'processing');
  70. try {
  71. // 准备当前集的数据
  72. $episodeData = $this->requestData;
  73. $episodeData['episode_number'] = $currentEpisodeNumber;
  74. $episodeData['prompt'] = '确认分镜大纲';
  75. // 调用非流式生成方法
  76. $result = $deepSeekService->chatForAceNonStream($episodeData);
  77. // 标记当前集完成
  78. $this->updateTaskProgress($currentEpisodeNumber, 'completed', $result);
  79. } catch (\Exception $e) {
  80. // 标记当前集失败
  81. $this->updateTaskProgress($currentEpisodeNumber, 'failed', null, $e->getMessage());
  82. // 记录错误日志
  83. logDB('batch_episode_generation', 'error', "第{$currentEpisodeNumber}集生成失败", [
  84. 'task_id' => $this->taskId,
  85. 'anime_id' => $this->animeId,
  86. 'episode_number' => $currentEpisodeNumber,
  87. 'error' => $e->getMessage(),
  88. 'trace' => $e->getTraceAsString()
  89. ]);
  90. // 继续生成下一集(可选:根据需求决定是否中断整个任务)
  91. // throw $e; // 如果要中断整个任务,取消注释这行
  92. }
  93. }
  94. // 标记整个任务完成
  95. DB::table('mp_batch_episode_generation_tasks')
  96. ->where('id', $this->taskId)
  97. ->update([
  98. 'status' => 'completed',
  99. 'completed_at' => now(),
  100. 'updated_at' => now()
  101. ]);
  102. } catch (\Exception $e) {
  103. // 标记整个任务失败
  104. DB::table('mp_batch_episode_generation_tasks')
  105. ->where('id', $this->taskId)
  106. ->update([
  107. 'status' => 'failed',
  108. 'error_message' => $e->getMessage(),
  109. 'updated_at' => now()
  110. ]);
  111. // 记录错误日志
  112. logDB('batch_episode_generation', 'error', '批量生成任务失败', [
  113. 'task_id' => $this->taskId,
  114. 'anime_id' => $this->animeId,
  115. 'error' => $e->getMessage(),
  116. 'trace' => $e->getTraceAsString()
  117. ]);
  118. throw $e;
  119. }
  120. }
  121. /**
  122. * 更新任务进度
  123. */
  124. private function updateTaskProgress($episodeNumber, $status, $result = null, $errorMessage = null)
  125. {
  126. $updateData = [
  127. 'current_episode' => $episodeNumber,
  128. 'updated_at' => now()
  129. ];
  130. if ($status === 'completed') {
  131. $updateData['completed_episodes'] = DB::raw('completed_episodes + 1');
  132. }
  133. if ($errorMessage) {
  134. $updateData['error_message'] = $errorMessage;
  135. }
  136. DB::table('mp_batch_episode_generation_tasks')
  137. ->where('id', $this->taskId)
  138. ->update($updateData);
  139. // 保存每集的详细状态
  140. DB::table('mp_batch_episode_generation_details')->insert([
  141. 'task_id' => $this->taskId,
  142. 'episode_number' => $episodeNumber,
  143. 'status' => $status,
  144. 'result_data' => $result ? json_encode($result, JSON_UNESCAPED_UNICODE) : null,
  145. 'error_message' => $errorMessage,
  146. 'created_at' => now(),
  147. 'updated_at' => now()
  148. ]);
  149. }
  150. /**
  151. * 任务失败处理
  152. */
  153. public function failed(\Throwable $exception)
  154. {
  155. DB::table('mp_batch_episode_generation_tasks')
  156. ->where('id', $this->taskId)
  157. ->update([
  158. 'status' => 'failed',
  159. 'error_message' => $exception->getMessage(),
  160. 'updated_at' => now()
  161. ]);
  162. logDB('batch_episode_generation', 'error', '批量生成任务彻底失败', [
  163. 'task_id' => $this->taskId,
  164. 'anime_id' => $this->animeId,
  165. 'error' => $exception->getMessage()
  166. ]);
  167. }
  168. }