|
|
@@ -26,6 +26,21 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 视频生成成功计费(事务内调用,真实失败抛错触发整体回滚)
|
|
|
+ *
|
|
|
+ * @param MpGenerateVideoTask $task
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ private function chargeVideoTaskInTransaction(MpGenerateVideoTask $task): void
|
|
|
+ {
|
|
|
+ $result = $this->pointsService->recordVideoTaskCharge($task);
|
|
|
+ if (empty($result['charged'])
|
|
|
+ && !in_array((string)($result['reason'] ?? ''), ['already_charged', 'no_charge_info'], true)) {
|
|
|
+ throw new \Exception('视频计费失败: ' . (string)($result['reason'] ?? 'unknown'));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 构建视频任务计费信息
|
|
|
*
|
|
|
* @param array $params 创建任务参数
|
|
|
@@ -410,11 +425,17 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
|
|
|
// 更新分镜表(兼容act模式)
|
|
|
- $this->updateSegmentTable($task, $segmentUpdateData);
|
|
|
+ $updateSegmentResult = $this->updateSegmentTable($task, $segmentUpdateData);
|
|
|
+ if ($updateSegmentResult === false || $updateSegmentResult === 0) {
|
|
|
+ throw new \Exception('更新分镜表失败: 未找到对应的分镜记录');
|
|
|
+ }
|
|
|
|
|
|
// 添加视频生成对话记录
|
|
|
$this->addVideoGenerationRecords($task, $segment_id, $statusInfo['result_url']);
|
|
|
|
|
|
+ // 视频生成成功,记录计费明细并扣减用户积分(与任务状态/分镜同事务)
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+
|
|
|
DB::commit();
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
@@ -427,11 +448,19 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
} else {
|
|
|
// 没有segment_id的情况下,直接更新任务状态
|
|
|
- $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+ $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+ DB::commit();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+ dLog('generate')->error('视频任务成功处理失败,已回滚', [
|
|
|
+ 'task_id' => $task->id,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // 视频生成成功,记录计费明细并扣减用户积分
|
|
|
- $this->pointsService->recordVideoTaskCharge($task);
|
|
|
} elseif ($statusInfo['status'] === 'failed') {
|
|
|
logDB('generate', 'error', '即梦AI视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
|
|
|
$task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, $statusInfo);
|
|
|
@@ -687,11 +716,17 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
|
|
|
// 更新分镜表(兼容act模式)
|
|
|
- $this->updateSegmentTable($task, $segmentUpdateData);
|
|
|
+ $updateSegmentResult = $this->updateSegmentTable($task, $segmentUpdateData);
|
|
|
+ if ($updateSegmentResult === false || $updateSegmentResult === 0) {
|
|
|
+ throw new \Exception('更新分镜表失败: 未找到对应的分镜记录');
|
|
|
+ }
|
|
|
|
|
|
// 添加视频生成对话记录
|
|
|
$this->addVideoGenerationRecords($task, $segment_id, $statusInfo['result_url']);
|
|
|
|
|
|
+ // 视频生成成功,记录计费明细并扣减用户积分(与任务状态/分镜同事务)
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+
|
|
|
DB::commit();
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
@@ -704,11 +739,19 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
} else {
|
|
|
// 没有segment_id的情况下,直接更新任务状态
|
|
|
- $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+ $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+ DB::commit();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+ dLog('generate')->error('视频任务成功处理失败,已回滚', [
|
|
|
+ 'task_id' => $task->id,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // 视频生成成功,记录计费明细并扣减用户积分
|
|
|
- $this->pointsService->recordVideoTaskCharge($task);
|
|
|
} elseif ($statusInfo['status'] === 'failed') {
|
|
|
logDB('generate', 'error', 'Seedance视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
|
|
|
$task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
|
|
|
@@ -1020,14 +1063,13 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 更新任务记录
|
|
|
- $task->update($updateData);
|
|
|
-
|
|
|
- // 如果任务成功,更新分镜表
|
|
|
+ // 更新任务记录(成功时与分镜同步、计费整体同事务)
|
|
|
if ($taskStatus === MpGenerateVideoTask::STATUS_SUCCESS && isset($updateData['result_url'])) {
|
|
|
try {
|
|
|
DB::beginTransaction();
|
|
|
|
|
|
+ $task->update($updateData);
|
|
|
+
|
|
|
$now = date('Y-m-d H:i:s');
|
|
|
|
|
|
// 获取分镜ID(兼容分镜模式和全能模式)
|
|
|
@@ -1102,6 +1144,9 @@ class AIVideoGenerationService
|
|
|
dLog('generate')->info('Seedance 分镜表更新成功: ' . $segmentId);
|
|
|
}
|
|
|
|
|
|
+ // 视频生成成功,记录计费明细并扣减用户积分(与任务状态/分镜同事务)
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+
|
|
|
DB::commit();
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
@@ -1115,18 +1160,31 @@ class AIVideoGenerationService
|
|
|
logDB('generate', 'error', 'Seedance分镜表更新失败', $logData);
|
|
|
}
|
|
|
} elseif ($taskStatus === MpGenerateVideoTask::STATUS_FAILED) {
|
|
|
- // 任务失败,更新分镜表状态
|
|
|
+ // 任务失败:更新任务记录与分镜表状态
|
|
|
+ $task->update($updateData);
|
|
|
DB::table('mp_episode_segments')
|
|
|
->where('video_task_id', $task->id)
|
|
|
->update([
|
|
|
'video_task_status' => '失败',
|
|
|
'updated_at' => date('Y-m-d H:i:s')
|
|
|
]);
|
|
|
- }
|
|
|
-
|
|
|
- // 视频生成成功,记录计费明细并扣减用户积分
|
|
|
- if ($taskStatus === MpGenerateVideoTask::STATUS_SUCCESS) {
|
|
|
- $this->pointsService->recordVideoTaskCharge($task);
|
|
|
+ } elseif ($taskStatus === MpGenerateVideoTask::STATUS_SUCCESS) {
|
|
|
+ // 成功但无结果URL:任务状态与计费同事务
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+ $task->update($updateData);
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+ DB::commit();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+ dLog('generate')->error('视频任务成功处理失败,已回滚', [
|
|
|
+ 'task_id' => $task->id,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 处理中或其他状态:更新任务记录
|
|
|
+ $task->update($updateData);
|
|
|
}
|
|
|
|
|
|
dLog('generate')->info('Seedance 回调处理完成: ' . $taskId . ', 状态: ' . $taskStatus);
|
|
|
@@ -1597,11 +1655,17 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
|
|
|
// 更新分镜表(兼容act模式)
|
|
|
- $this->updateSegmentTable($task, $segmentUpdateData);
|
|
|
+ $updateSegmentResult = $this->updateSegmentTable($task, $segmentUpdateData);
|
|
|
+ if ($updateSegmentResult === false || $updateSegmentResult === 0) {
|
|
|
+ throw new \Exception('更新分镜表失败: 未找到对应的分镜记录');
|
|
|
+ }
|
|
|
|
|
|
// 添加视频生成对话记录
|
|
|
$this->addVideoGenerationRecords($task, $segment_id, $statusInfo['result_url']);
|
|
|
|
|
|
+ // 视频生成成功,记录计费明细并扣减用户积分(与任务状态/分镜同事务)
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+
|
|
|
DB::commit();
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
@@ -1614,11 +1678,19 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
} else {
|
|
|
// 没有segment_id的情况下,直接更新任务状态
|
|
|
- $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+ $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+ DB::commit();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+ dLog('generate')->error('视频任务成功处理失败,已回滚', [
|
|
|
+ 'task_id' => $task->id,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // 视频生成成功,记录计费明细并扣减用户积分
|
|
|
- $this->pointsService->recordVideoTaskCharge($task);
|
|
|
} elseif ($statusInfo['status'] === 'failed') {
|
|
|
$task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
|
|
|
'error_message' => $statusInfo['error_message'],
|
|
|
@@ -2717,7 +2789,10 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
|
|
|
// 更新分镜表(兼容act模式)
|
|
|
- $this->updateSegmentTable($task, $segmentUpdateData);
|
|
|
+ $updateSegmentResult = $this->updateSegmentTable($task, $segmentUpdateData);
|
|
|
+ if ($updateSegmentResult === false || $updateSegmentResult === 0) {
|
|
|
+ throw new \Exception('更新分镜表失败: 未找到对应的分镜记录');
|
|
|
+ }
|
|
|
|
|
|
// 添加视频生成对话记录
|
|
|
$this->addVideoGenerationRecords($task, $segment_id, $statusInfo['result_url']);
|
|
|
@@ -2747,6 +2822,9 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 视频生成成功,记录计费明细并扣减用户积分(与任务状态/分镜同事务)
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+
|
|
|
DB::commit();
|
|
|
// 从Redis中移除
|
|
|
Redis::srem('anime_act_first_frame_urls', $act_id);
|
|
|
@@ -2761,11 +2839,19 @@ class AIVideoGenerationService
|
|
|
}
|
|
|
} else {
|
|
|
// 没有segment_id的情况下,直接更新任务状态
|
|
|
- $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+ $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
|
|
|
+ $this->chargeVideoTaskInTransaction($task);
|
|
|
+ DB::commit();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+ dLog('generate')->error('视频任务成功处理失败,已回滚', [
|
|
|
+ 'task_id' => $task->id,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // 视频生成成功,记录计费明细并扣减用户积分
|
|
|
- $this->pointsService->recordVideoTaskCharge($task);
|
|
|
} elseif ($statusInfo['status'] === 'failed') {
|
|
|
logDB('generate', 'error', '统一API视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
|
|
|
$task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
|