TextScriptGenerateRunCommand.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Services\DeepSeek\DeepSeekService;
  4. use Illuminate\Console\Command;
  5. use Illuminate\Support\Facades\DB;
  6. /**
  7. * 剧本资产生成异步任务 worker
  8. *
  9. * 由 text:generate:dispatch 拉起;通过 MySQL 命名锁防止同一任务被重复执行。
  10. */
  11. class TextScriptGenerateRunCommand extends Command
  12. {
  13. /**
  14. * 任务处理锁前缀(配合 MySQL GET_LOCK 使用)
  15. */
  16. public const LOCK_PREFIX = 'script_text_generate_';
  17. /**
  18. * The name and signature of the console command.
  19. *
  20. * @var string
  21. */
  22. protected $signature = 'text:generate:run {task_id : 剧本资产生成任务ID}';
  23. /**
  24. * The console command description.
  25. *
  26. * @var string
  27. */
  28. protected $description = '剧本资产生成worker:执行指定任务的流式模型生成并落库';
  29. /**
  30. * @var DeepSeekService
  31. */
  32. protected $deepSeekService;
  33. /**
  34. * Create a new command instance.
  35. *
  36. * @return void
  37. */
  38. public function __construct(DeepSeekService $deepSeekService)
  39. {
  40. parent::__construct();
  41. $this->deepSeekService = $deepSeekService;
  42. }
  43. /**
  44. * Execute the console command.
  45. *
  46. * @return int
  47. */
  48. public function handle()
  49. {
  50. set_time_limit(0);
  51. $taskId = (int)$this->argument('task_id');
  52. $lockName = self::LOCK_PREFIX . $taskId;
  53. // 非阻塞抢占该任务的处理锁;抢不到说明已有其他进程正在处理
  54. $acquired = DB::selectOne('SELECT GET_LOCK(?, 0) AS acquired', [$lockName]);
  55. if (!$acquired || (int)$acquired->acquired !== 1) {
  56. dLog('command')->info("task_id: {$taskId} 正在被其他进程处理,本次直接退出");
  57. return 0;
  58. }
  59. dLog('command')->info("task_id: {$taskId} 抢占处理锁成功,开始处理...");
  60. try {
  61. $result = $this->deepSeekService->runScriptGenerateTaskAsync($taskId);
  62. dLog('command')->info('task_id: ' . $taskId . ' 处理结果: ' . json_encode($result, JSON_UNESCAPED_UNICODE));
  63. if (empty($result['ok'])) {
  64. logDB('command', 'error', '剧本资产生成worker异常', [
  65. 'task_id' => $taskId,
  66. 'status' => $result['status'] ?? null,
  67. 'error' => $result['error'] ?? '未知错误',
  68. ]);
  69. }
  70. } catch (\Throwable $e) {
  71. dLog('command')->error("task_id: {$taskId} 处理异常: " . $e->getMessage());
  72. logDB('command', 'error', '剧本资产生成worker异常', [
  73. 'task_id' => $taskId,
  74. 'error' => $e->getMessage(),
  75. ]);
  76. } finally {
  77. // 显式释放处理锁;即使进程异常退出,连接断开后 MySQL 也会自动释放
  78. DB::statement('SELECT RELEASE_LOCK(?)', [$lockName]);
  79. dLog('command')->info("task_id: {$taskId} 处理结束,已释放处理锁");
  80. }
  81. return 0;
  82. }
  83. }