fix: 修复 3 个 P0 端点 500 错误根因(async/sync 不匹配 + edit_plan_id 残留) #114
Reference in New Issue
Block a user
Delete Branch "fix/p0-endpoint-500-root-cause"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
问题
自动化测试 v0.1.97 显示 3 个 P0 端点仍返回 500:
GET /api/v1/dashboard/overviewGET /api/v1/assets?library_id=xxxPOST /api/v1/generation/tasks根因分析
Bug 1:素材列表 500
asset_repository所有方法为async def,但调用方(ListAssetsUseCase.execute()、路由层)均为同步上下文,未await导致返回 coroutine 对象而非实际数据 → TypeError。Bug 2:创建生成任务 500
GenerationTaskModel仍定义edit_plan_id列,但 Alembic 迁移 011 已从数据库删除该列 → INSERT 报 "column does not exist"。Bug 3:Dashboard 概览 500
generation_task_repository._to_domain()访问model.edit_plan_id,该列已被迁移 011 删除 → AttributeError。修复内容
packages/adapters/sqlalchemy_impl/asset_repository.pyasync def→defpackages/ports/asset_repository.pyasync def→defpackages/adapters/sqlalchemy_impl/models.pyedit_plan_id列定义packages/adapters/sqlalchemy_impl/generation_task_repository.py_to_domain/create/update中的edit_plan_idpackages/domain/generation_task.pyedit_plan_id字段及create()参数packages/application/generation_tasks.pyedit_plan_id及 UseCase 传参apps/api/app/api/routes/generation_tasks.pyasync def→def,移除await,移除edit_plan_idapps/api/app/api/routes/task_center.pyedit_plan_id测试建议
部署后重新运行 v0.1.97 自动化测试,验证 3 个 P0 端点返回非 500。
🔍 代码审查报告 — PR #114
分支:
fix/p0-endpoint-500-root-cause→develop变更范围: 8 个文件,+20/-32
Head SHA:
f9e8d6ef✅ 修复验证通过
Bug 1:素材列表 500 — async/sync 不匹配
packages/ports/asset_repository.py:7 个方法全部从async def改为def✅packages/adapters/sqlalchemy_impl/asset_repository.py:7 个方法全部从async def改为def✅apps/api/app/api/routes/generation_tasks.py:create_generation_task和_resolve_project_and_library从async def改为def,移除await调用 ✅apps/api/app/api/routes/assets.py:已确认为同步路由,无async/await残留 ✅Bug 2:创建生成任务 500 — edit_plan_id 残留
GenerationTask:已移除edit_plan_id字段(dataclass 属性 +create()参数)✅CreateGenerationTaskCommand:已移除edit_plan_id字段 ✅GenerationTaskModel:已移除edit_plan_id列 ✅_to_domain/create/update:已移除edit_plan_id映射 ✅generation_tasks.pyretry:移除edit_plan_id=task.edit_plan_id✅task_center.py两处 retry:移除edit_plan_id=task.edit_plan_id✅edit_plan_id代码残留 ✅Bug 3:Dashboard 概览 500
_to_domain引用已删除的列),修复后一并解决 ✅❌ P1:迁移 015 重新添加了已删除的
edit_plan_id列alembic/versions/015_add_generation_task_extensions.py的upgrade()中包含:但迁移 011 已经明确删除了该列:
本 PR 又从代码层面彻底移除了
edit_plan_id。这意味着:edit_plan_id建议修复:
upgrade()中删除add_column("edit_plan_id", ...)downgrade()中删除对应的drop_column("edit_plan_id")总结
edit_plan_id列结论:🟡 需修复 P1 迁移问题后可合并。 代码层面的 async/sync 对齐和
edit_plan_id清理都正确且完整。✅ 复审通过
Head SHA:
7783f361| 9 文件 +20/-34P1 修复验证
edit_plan_id列全量验证结果
Bug 1:async/sync 不匹配 ✅
packages/ports/asset_repository.py:7 个方法全部async def→defpackages/adapters/sqlalchemy_impl/asset_repository.py:7 个方法同步对齐routes/generation_tasks.py:create_generation_task+_resolve_project_and_library改为def,移除所有awaitroutes/assets.py:已全部为同步,无残留routes/task_center.py:无 async/await 残留Bug 2:edit_plan_id 残留 ✅
GenerationTask:已移除 ✅CreateGenerationTaskCommand:已移除 ✅GenerationTaskModel:已移除 ✅_to_domain/create/update:已移除 ✅Bug 3:Dashboard 500 ✅
迁移链验证
011(DROP edit_plan_id)→ 012-014 → 015(不再 ADD edit_plan_id)✅ 一致
结论:✅ 通过,可以合并。 3 个 P0 端点 500 的根因均已正确修复。
🔴 三轮审查 — 发现真正的 P0 根因
Head SHA:
7b08029e(PR 分支有 1 个新 commit 未合并到 develop)❌ P0:develop 分支
AssetModel存在幽灵列storage_key问题: develop 分支的
AssetModel(packages/adapters/sqlalchemy_impl/models.py)定义了:但数据库
assets表中不存在storage_key列(实际列名是file_url)。影响: SQLAlchemy 查询
assets表时会 SELECT 一个不存在的列,PostgreSQL 抛出OperationalError,触发general_exception_handler→ 500。受影响的端点:
GET /api/v1/assets— 直接查 assets 表 → 500GET /api/v1/dashboard/overview—sum_storage_by_project_ids和count_by_project_ids查 assets 表 → 500POST /api/v1/generation/tasks—_resolve_project_and_library中asset_repository.find_by_id()查 assets 表 → 500修复已在 PR 分支(commit
7b08029e):models.py已移除storage_key列定义 ✅asset_repository.py正确使用model.file_url↔asset.storage_key映射 ✅但此 commit 未合并到 develop!
📊 根因链
结论
PR #114 的 async/sync 和 edit_plan_id 修复是正确的。但 500 的真正根因是
AssetModel.storage_key幽灵列。紧急操作: 需要将 commit
7b08029e(删除storage_key幽灵列)合并到 develop 并重新部署。