fix: 修复 3 个 P0 端点 500 错误根因(async/sync 不匹配 + edit_plan_id 残留) #114

Merged
xiaoxia merged 2 commits from fix/p0-endpoint-500-root-cause into develop 2026-06-29 20:28:26 +08:00
9 changed files with 20 additions and 34 deletions
@@ -18,7 +18,6 @@ depends_on = None
def upgrade() -> None:
op.add_column("generation_tasks", sa.Column("edit_plan_id", sa.String(32), nullable=False, server_default=""))
op.add_column("generation_tasks", sa.Column("template_id", sa.String(36), nullable=False, server_default=""))
op.add_column("generation_tasks", sa.Column("asset_ids", mysql.JSON(), nullable=False, server_default="[]"))
op.add_column("generation_tasks", sa.Column("title_ids", mysql.JSON(), nullable=False, server_default="[]"))
@@ -33,4 +32,3 @@ def downgrade() -> None:
op.drop_column("generation_tasks", "title_ids")
op.drop_column("generation_tasks", "asset_ids")
op.drop_column("generation_tasks", "template_id")
op.drop_column("generation_tasks", "edit_plan_id")
+5 -6
View File
@@ -84,7 +84,7 @@ def _ensure_library_has_ready_video_assets(assets) -> None:
)
async def _resolve_project_and_library(
def _resolve_project_and_library(
request: CreateGenerationTaskRequest,
project_repository: Any,
asset_library_repository: Any,
@@ -104,7 +104,7 @@ async def _resolve_project_and_library(
# 模板模式:project_id 未提供时,从 asset_ids 反查所属 project
if not project_id and request.asset_ids:
first_asset_id = request.asset_ids[0]
asset = await asset_repository.find_by_id(first_asset_id)
asset = asset_repository.find_by_id(first_asset_id)
if asset is not None:
project_id = asset.project_id
if not asset_library_id:
@@ -122,7 +122,7 @@ async def _resolve_project_and_library(
@router.post("/tasks", response_model=GenerationTaskResponse)
async def create_generation_task(
def create_generation_task(
request: CreateGenerationTaskRequest,
authenticated_user: AuthenticatedUser = Depends(get_current_user),
generation_task_repository: Any = Depends(get_generation_task_repository),
@@ -130,7 +130,7 @@ async def create_generation_task(
asset_library_repository: Any = Depends(get_asset_library_repository),
asset_repository: Any = Depends(get_asset_repository),
) -> GenerationTaskResponse:
project_id, asset_library_id = await _resolve_project_and_library(
project_id, asset_library_id = _resolve_project_and_library(
request, project_repository, asset_library_repository, asset_repository, authenticated_user
)
@@ -140,7 +140,7 @@ async def create_generation_task(
if library is None or (project_id and library.project_id != project_id):
raise HTTPException(status_code=404, detail=f"AssetLibrary {asset_library_id} not found")
assets = await asset_repository.find_by_library(asset_library_id)
assets = asset_repository.find_by_library(asset_library_id)
_ensure_library_has_ready_video_assets(assets)
use_case = CreateGenerationTaskUseCase(generation_task_repository)
@@ -229,7 +229,6 @@ def retry_generation_task(
asset_library_id=task.asset_library_id,
strategy_id=task.strategy_id,
voice_library_id=task.voice_library_id,
edit_plan_id=task.edit_plan_id,
template_id=task.template_id,
asset_ids=task.asset_ids,
title_ids=task.title_ids,
-2
View File
@@ -146,7 +146,6 @@ def retry_task_by_id(
asset_library_id=task.asset_library_id,
strategy_id=task.strategy_id,
voice_library_id=task.voice_library_id,
edit_plan_id=task.edit_plan_id,
template_id=task.template_id,
asset_ids=task.asset_ids,
title_ids=task.title_ids,
@@ -229,7 +228,6 @@ def retry_project_task(
asset_library_id=task.asset_library_id,
strategy_id=task.strategy_id,
voice_library_id=task.voice_library_id,
edit_plan_id=task.edit_plan_id,
template_id=task.template_id,
asset_ids=task.asset_ids,
title_ids=task.title_ids,
@@ -11,7 +11,7 @@ class SQLAlchemyAssetRepository:
def __init__(self, session: Session):
self.session = session
async def find_by_library(
def find_by_library(
self,
library_id: str,
skip: int = 0,
@@ -22,7 +22,7 @@ class SQLAlchemyAssetRepository:
).offset(skip).limit(limit).all()
return [self._to_domain(model) for model in models]
async def find_by_project(
def find_by_project(
self,
project_id: str,
skip: int = 0,
@@ -33,7 +33,7 @@ class SQLAlchemyAssetRepository:
).offset(skip).limit(limit).all()
return [self._to_domain(model) for model in models]
async def find_by_id(self, asset_id: str) -> Asset | None:
def find_by_id(self, asset_id: str) -> Asset | None:
model = self.session.query(AssetModel).filter(AssetModel.id == asset_id).first()
if model is None:
return None
@@ -42,7 +42,7 @@ class SQLAlchemyAssetRepository:
def get(self, asset_id: str) -> Asset | None:
return self.find_by_id(asset_id)
async def create(self, asset: Asset) -> Asset:
def create(self, asset: Asset) -> Asset:
now = datetime.now(timezone.utc)
model = AssetModel(
id=asset.id,
@@ -70,7 +70,7 @@ class SQLAlchemyAssetRepository:
self.session.commit()
return asset
async def update(self, asset: Asset) -> Asset:
def update(self, asset: Asset) -> Asset:
model = self.session.query(AssetModel).filter(AssetModel.id == asset.id).first()
if model is None:
raise ValueError(f"Asset {asset.id} not found")
@@ -92,7 +92,7 @@ class SQLAlchemyAssetRepository:
self.session.commit()
return asset
async def delete(self, asset_id: str) -> bool:
def delete(self, asset_id: str) -> bool:
model = self.session.query(AssetModel).filter(AssetModel.id == asset_id).first()
if model:
self.session.delete(model)
@@ -100,7 +100,7 @@ class SQLAlchemyAssetRepository:
return True
return False
async def count_by_project(self, project_id: str) -> int:
def count_by_project(self, project_id: str) -> int:
return self.session.query(AssetModel).filter(
AssetModel.project_id == project_id
).count()
@@ -12,7 +12,6 @@ def _to_domain(model: GenerationTaskModel) -> GenerationTask:
strategy_id=model.strategy_id,
asset_library_id=model.asset_library_id,
voice_library_id=model.voice_library_id,
edit_plan_id=model.edit_plan_id,
template_id=model.template_id,
asset_ids=list(model.asset_ids or []),
title_ids=list(model.title_ids or []),
@@ -39,7 +38,6 @@ class SQLAlchemyGenerationTaskRepository:
strategy_id=task.strategy_id,
asset_library_id=task.asset_library_id,
voice_library_id=task.voice_library_id,
edit_plan_id=task.edit_plan_id,
template_id=task.template_id,
asset_ids=task.asset_ids,
title_ids=task.title_ids,
@@ -106,7 +104,6 @@ class SQLAlchemyGenerationTaskRepository:
model.asset_library_id = task.asset_library_id
model.strategy_id = task.strategy_id
model.voice_library_id = task.voice_library_id
model.edit_plan_id = task.edit_plan_id
model.template_id = task.template_id
model.asset_ids = task.asset_ids
model.title_ids = task.title_ids
@@ -143,7 +143,6 @@ class GenerationTaskModel(Base):
strategy_id = Column(String(32), nullable=False, default="")
asset_library_id = Column(String(32), nullable=False, default="", index=True)
voice_library_id = Column(String(32), nullable=False, default="")
edit_plan_id = Column(String(32), nullable=False, default="")
template_id = Column(String(36), nullable=False, default="", index=True)
asset_ids = Column(JSON, nullable=False, default=list)
title_ids = Column(JSON, nullable=False, default=list)
-2
View File
@@ -13,7 +13,6 @@ class CreateGenerationTaskCommand:
asset_library_id: str = ""
strategy_id: str = ""
voice_library_id: str = ""
edit_plan_id: str = ""
template_id: str = ""
asset_ids: list[str] = field(default_factory=list)
title_ids: list[str] = field(default_factory=list)
@@ -32,7 +31,6 @@ class CreateGenerationTaskUseCase:
asset_library_id=command.asset_library_id,
strategy_id=command.strategy_id,
voice_library_id=command.voice_library_id,
edit_plan_id=command.edit_plan_id,
template_id=command.template_id,
asset_ids=command.asset_ids,
title_ids=command.title_ids,
-3
View File
@@ -21,7 +21,6 @@ class GenerationTask:
asset_library_id: str
strategy_id: str = ""
voice_library_id: str = ""
edit_plan_id: str = ""
template_id: str = ""
asset_ids: list[str] = field(default_factory=list)
title_ids: list[str] = field(default_factory=list)
@@ -43,7 +42,6 @@ class GenerationTask:
*,
strategy_id: str = "",
voice_library_id: str = "",
edit_plan_id: str = "",
template_id: str = "",
asset_ids: list[str] | None = None,
title_ids: list[str] | None = None,
@@ -60,7 +58,6 @@ class GenerationTask:
asset_library_id=asset_library_id.strip(),
strategy_id=strategy_id.strip(),
voice_library_id=voice_library_id.strip(),
edit_plan_id=edit_plan_id.strip(),
template_id=template_id.strip(),
asset_ids=list(asset_ids) if asset_ids else [],
title_ids=list(title_ids) if title_ids else [],
+8 -8
View File
@@ -1,4 +1,4 @@
"""兼容层:旧素材仓储接口定义,保留给遗留异步适配器使用"""
"""素材仓储接口定义。"""
from abc import ABC, abstractmethod
@@ -7,15 +7,15 @@ from packages.domain import Asset
class AssetRepository(ABC):
@abstractmethod
async def create(self, asset: Asset) -> Asset:
def create(self, asset: Asset) -> Asset:
pass
@abstractmethod
async def find_by_id(self, asset_id: str) -> Asset | None:
def find_by_id(self, asset_id: str) -> Asset | None:
pass
@abstractmethod
async def find_by_project(
def find_by_project(
self,
project_id: str,
skip: int = 0,
@@ -24,7 +24,7 @@ class AssetRepository(ABC):
pass
@abstractmethod
async def find_by_library(
def find_by_library(
self,
library_id: str,
skip: int = 0,
@@ -33,15 +33,15 @@ class AssetRepository(ABC):
pass
@abstractmethod
async def update(self, asset: Asset) -> Asset:
def update(self, asset: Asset) -> Asset:
pass
@abstractmethod
async def delete(self, asset_id: str) -> bool:
def delete(self, asset_id: str) -> bool:
pass
@abstractmethod
async def count_by_project(self, project_id: str) -> int:
def count_by_project(self, project_id: str) -> int:
pass
@abstractmethod