上传素材管控-历史素材success
This commit is contained in:
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
from datetime import datetime
|
||||
from types import SimpleNamespace
|
||||
|
||||
from fastapi import APIRouter, Body, Depends, HTTPException, Path, Query
|
||||
from fastapi import APIRouter, Body, Depends, File, HTTPException, Path, Query, UploadFile
|
||||
from sqlalchemy import inspect as sa_inspect
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
@@ -35,6 +35,7 @@ from app.schemas.shot_replicate import (
|
||||
ShotReplicateTaskDetailOut,
|
||||
ShotReplicateVideoPromptSchemaUpdateRequest,
|
||||
ShotSegmentDeleteOut,
|
||||
ShotTaskSetDeleteOut,
|
||||
ShotSegmentDetailOut,
|
||||
ShotSegmentListOut,
|
||||
ShotSegmentReplicationCreateRequest,
|
||||
@@ -49,7 +50,6 @@ from app.schemas.shot_replicate import (
|
||||
from app.services.shot_replicate_flow_service import (
|
||||
_get_project_for_user,
|
||||
create_shot_replicate_project_from_segment,
|
||||
delete_shot_replicate_project,
|
||||
generate_image_from_prompt,
|
||||
generate_video_from_prompt,
|
||||
mark_shot_replicate_step_dispatch_failed,
|
||||
@@ -65,6 +65,7 @@ from app.services.shot_replicate_taskset_service import (
|
||||
create_segments_by_ai,
|
||||
create_task_set,
|
||||
delete_segment,
|
||||
delete_task_set,
|
||||
get_segment_for_user,
|
||||
list_segments,
|
||||
list_task_sets,
|
||||
@@ -83,6 +84,9 @@ from app.services.module_async_recovery_service import (
|
||||
register_shot_task_set_analysis_task,
|
||||
)
|
||||
from app.tasks.celery_app import celery_app
|
||||
from app.enums.upload_resource import UploadResourceEventEnum, UploadResourceModuleEnum, UploadResourceSourceModelEnum, UploadResourceTypeEnum
|
||||
from app.services.upload_resource import upload_reference_file, bind_upload_resources, cleanup_upload_resource_files_after_commit
|
||||
from app.services.upload_resource.log_service import log_upload_resource_exception, safe_rollback_with_log
|
||||
|
||||
MODULE = ModuleCodeEnum.SHOT_REPLICATE.value
|
||||
|
||||
@@ -245,6 +249,66 @@ async def get_spec():
|
||||
return ShotReplicateSpecOut()
|
||||
|
||||
|
||||
@router.post(
|
||||
"/upload-image",
|
||||
summary="上传拆镜复刻图片素材",
|
||||
description="上传后先记录为 pending UploadResource;创建拆镜复刻项目后绑定业务记录。",
|
||||
)
|
||||
async def upload_shot_replicate_image(
|
||||
file: UploadFile = File(...),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
result = await upload_reference_file(
|
||||
db,
|
||||
file=file,
|
||||
current_user=current_user,
|
||||
module=UploadResourceModuleEnum.SHOT_REPLICATE.value,
|
||||
resource_type=UploadResourceTypeEnum.IMAGE.value,
|
||||
gen_type="video",
|
||||
)
|
||||
await db.commit()
|
||||
return {
|
||||
"url": result.url,
|
||||
"filename": result.filename,
|
||||
"type": "image",
|
||||
"module": result.module,
|
||||
"resource_id": result.resource_id,
|
||||
"file_size_bytes": result.file_size_bytes,
|
||||
}
|
||||
|
||||
|
||||
@router.post(
|
||||
"/upload-video",
|
||||
summary="上传拆镜复刻视频素材",
|
||||
description="上传后先记录为 pending UploadResource;创建拆镜总任务集后绑定 ShotReplicateTaskSet。",
|
||||
)
|
||||
async def upload_shot_replicate_video(
|
||||
file: UploadFile = File(...),
|
||||
duration_seconds: float | None = Query(None, description="前端识别的视频时长秒数,可选"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
result = await upload_reference_file(
|
||||
db,
|
||||
file=file,
|
||||
current_user=current_user,
|
||||
module=UploadResourceModuleEnum.SHOT_REPLICATE.value,
|
||||
resource_type=UploadResourceTypeEnum.VIDEO.value,
|
||||
duration_seconds=duration_seconds,
|
||||
)
|
||||
await db.commit()
|
||||
return {
|
||||
"url": result.url,
|
||||
"filename": result.filename,
|
||||
"type": "video",
|
||||
"module": result.module,
|
||||
"resource_id": result.resource_id,
|
||||
"file_size_bytes": result.file_size_bytes,
|
||||
"duration_seconds": result.duration_seconds,
|
||||
}
|
||||
|
||||
|
||||
@router.post(
|
||||
"/task-sets",
|
||||
response_model=ShotTaskSetDetailOut,
|
||||
@@ -264,6 +328,16 @@ async def create_shot_task_set(
|
||||
try:
|
||||
task_set = await create_task_set(db, current_user=current_user, req=req)
|
||||
task_set_id = task_set.id
|
||||
await bind_upload_resources(
|
||||
db,
|
||||
user_id=current_user.id,
|
||||
module=UploadResourceModuleEnum.SHOT_REPLICATE.value,
|
||||
source_model=UploadResourceSourceModelEnum.SHOT_REPLICATE_TASK_SET.value,
|
||||
source_id=task_set_id,
|
||||
resource_ids=[req.video_resource_id],
|
||||
urls=[req.video_url],
|
||||
allow_common_migrate=True,
|
||||
)
|
||||
await db.commit()
|
||||
except HTTPException:
|
||||
await db.rollback()
|
||||
@@ -626,18 +700,69 @@ async def delete_shot_segment(
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
user_id = _safe_user_id(current_user)
|
||||
pending_ids: list[str] = []
|
||||
try:
|
||||
out = await delete_segment(db, current_user=current_user, segment_id=segment_id)
|
||||
pending_ids = list(out.pending_delete_resource_ids or [])
|
||||
await db.commit()
|
||||
return out
|
||||
except HTTPException:
|
||||
await db.rollback()
|
||||
except HTTPException as exc:
|
||||
await safe_rollback_with_log(
|
||||
db,
|
||||
event_type=UploadResourceEventEnum.SHOT_SEGMENT_DELETE_ROLLBACK_FAILED.value,
|
||||
message="删除拆镜片段 HTTPException 回滚失败",
|
||||
user_id=user_id,
|
||||
module=MODULE,
|
||||
detail={"segment_id": segment_id},
|
||||
original_exc=exc,
|
||||
)
|
||||
raise
|
||||
except Exception as exc:
|
||||
await db.rollback()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
await safe_rollback_with_log(
|
||||
db,
|
||||
event_type=UploadResourceEventEnum.SHOT_SEGMENT_DELETE_ROLLBACK_FAILED.value,
|
||||
message="删除拆镜片段主事务回滚失败",
|
||||
user_id=user_id,
|
||||
module=MODULE,
|
||||
detail={"segment_id": segment_id},
|
||||
original_exc=exc,
|
||||
)
|
||||
_log_api_exception_from_locals(exc, locals(), f"删除拆镜片段失败: {exc}")
|
||||
log_upload_resource_exception(
|
||||
event_type=UploadResourceEventEnum.SHOT_SEGMENT_DELETE_FAILED.value,
|
||||
message=f"删除拆镜片段失败: {exc}",
|
||||
user_id=user_id,
|
||||
module=MODULE,
|
||||
detail={"segment_id": segment_id},
|
||||
exc=exc,
|
||||
)
|
||||
raise HTTPException(status_code=500, detail=f"删除拆镜片段失败: {exc}")
|
||||
|
||||
if pending_ids:
|
||||
try:
|
||||
await cleanup_upload_resource_files_after_commit(db, resource_ids=pending_ids)
|
||||
await db.commit()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
await safe_rollback_with_log(
|
||||
db,
|
||||
event_type=UploadResourceEventEnum.SHOT_SEGMENT_DELETE_ROLLBACK_FAILED.value,
|
||||
message="删除拆镜片段 cleanup 事务回滚失败",
|
||||
user_id=user_id,
|
||||
module=MODULE,
|
||||
detail={"segment_id": segment_id, "pending_ids": pending_ids},
|
||||
original_exc=exc,
|
||||
)
|
||||
log_upload_resource_exception(
|
||||
event_type=UploadResourceEventEnum.SHOT_SEGMENT_DELETE_CLEANUP_FAILED.value,
|
||||
message=f"删除拆镜片段后清理真实文件失败: {exc}",
|
||||
user_id=user_id,
|
||||
resource_ids=pending_ids,
|
||||
module=MODULE,
|
||||
detail={"segment_id": segment_id},
|
||||
exc=exc,
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
@router.post(
|
||||
"/segments/{segment_id}/replication-projects",
|
||||
@@ -950,24 +1075,75 @@ async def generate_video(
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/projects/{project_id}",
|
||||
response_model=ShotReplicateDeleteOut,
|
||||
summary="软删除拆镜复刻项目",
|
||||
description="软删除拆镜复刻 ModuleGenerationProject,并联动软删除当前有效步骤和关联的 ChatGenerationTask。",
|
||||
"/task-sets/{task_set_id}",
|
||||
response_model=ShotTaskSetDeleteOut,
|
||||
summary="软删除拆镜任务集",
|
||||
description="软删除整个 ShotReplicateTaskSet,并联动软删除全部片段和片段内部复刻项目;UploadResource 真实文件在事务提交后清理。",
|
||||
)
|
||||
async def delete_project(
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
async def delete_shot_task_set(
|
||||
task_set_id: str = Path(..., description="拆镜任务集ID,即 shot_replicate_task_sets.id"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
user_id = _safe_user_id(current_user)
|
||||
pending_ids: list[str] = []
|
||||
try:
|
||||
out = await delete_shot_replicate_project(db, current_user=current_user, project_id=project_id)
|
||||
out = await delete_task_set(db, current_user=current_user, task_set_id=task_set_id)
|
||||
pending_ids = list(out.pending_delete_resource_ids or [])
|
||||
await db.commit()
|
||||
return out
|
||||
except HTTPException:
|
||||
await db.rollback()
|
||||
except HTTPException as exc:
|
||||
await safe_rollback_with_log(
|
||||
db,
|
||||
event_type=UploadResourceEventEnum.SHOT_TASK_SET_DELETE_ROLLBACK_FAILED.value,
|
||||
message="删除拆镜任务集 HTTPException 回滚失败",
|
||||
user_id=user_id,
|
||||
module=MODULE,
|
||||
detail={"task_set_id": task_set_id},
|
||||
original_exc=exc,
|
||||
)
|
||||
raise
|
||||
except Exception as exc:
|
||||
await db.rollback()
|
||||
_log_api_exception_from_locals(exc, locals(), f"删除拆镜复刻项目失败: {exc}")
|
||||
raise HTTPException(status_code=500, detail=f"删除拆镜复刻项目失败: {exc}")
|
||||
except Exception as exc: # noqa: BLE001
|
||||
await safe_rollback_with_log(
|
||||
db,
|
||||
event_type=UploadResourceEventEnum.SHOT_TASK_SET_DELETE_ROLLBACK_FAILED.value,
|
||||
message="删除拆镜任务集主事务回滚失败",
|
||||
user_id=user_id,
|
||||
module=MODULE,
|
||||
detail={"task_set_id": task_set_id},
|
||||
original_exc=exc,
|
||||
)
|
||||
_log_api_exception_from_locals(exc, locals(), f"删除拆镜任务集失败: {exc}")
|
||||
log_upload_resource_exception(
|
||||
event_type=UploadResourceEventEnum.SHOT_TASK_SET_DELETE_FAILED.value,
|
||||
message=f"删除拆镜任务集失败: {exc}",
|
||||
user_id=user_id,
|
||||
module=MODULE,
|
||||
detail={"task_set_id": task_set_id},
|
||||
exc=exc,
|
||||
)
|
||||
raise HTTPException(status_code=500, detail=f"删除拆镜任务集失败: {exc}")
|
||||
|
||||
if pending_ids:
|
||||
try:
|
||||
await cleanup_upload_resource_files_after_commit(db, resource_ids=pending_ids)
|
||||
await db.commit()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
await safe_rollback_with_log(
|
||||
db,
|
||||
event_type=UploadResourceEventEnum.SHOT_TASK_SET_DELETE_ROLLBACK_FAILED.value,
|
||||
message="删除拆镜任务集 cleanup 事务回滚失败",
|
||||
user_id=user_id,
|
||||
module=MODULE,
|
||||
detail={"task_set_id": task_set_id, "pending_ids": pending_ids},
|
||||
original_exc=exc,
|
||||
)
|
||||
log_upload_resource_exception(
|
||||
event_type=UploadResourceEventEnum.SHOT_TASK_SET_DELETE_CLEANUP_FAILED.value,
|
||||
message=f"删除拆镜任务集后清理真实文件失败: {exc}",
|
||||
user_id=user_id,
|
||||
resource_ids=pending_ids,
|
||||
module=MODULE,
|
||||
detail={"task_set_id": task_set_id},
|
||||
exc=exc,
|
||||
)
|
||||
return out
|
||||
|
||||
Reference in New Issue
Block a user