fix: 封面模板 API 错误处理加固,表不存在时降级返回空列表 #1329

Merged
xiaoxia merged 2 commits from fix/cover-templates-error-handling into develop 2026-08-10 10:40:11 +08:00
Owner

背景

封面模板功能(PR #1323)已合入 develop,但 staging 环境数据库迁移 055_cover_templates 未执行,cover_templates 表不存在,导致 GET /api/v1/cover-templates 返回 500。

改动

  1. GET /cover-templates:捕获 OperationalError/ProgrammingError,降级返回 {"items": [], "total": 0} + warning 日志
  2. POST/PUT/DELETE:捕获同类异常,返回 503(封面模板服务暂不可用)而非 500
  3. 新增 4 个错误处理单测(共 32 个 passed)

交付标准

  • staging API 异常时降级返回空列表/503 而非 500
  • 32 单测通过 + ruff lint 通过
  • CI 全绿后合入 develop

注意:本 PR 不直接执行 staging 数据库迁移,迁移会在 CI 部署时自动执行(alembic upgrade head)。

## 背景 封面模板功能(PR #1323)已合入 develop,但 staging 环境数据库迁移 055_cover_templates 未执行,cover_templates 表不存在,导致 GET /api/v1/cover-templates 返回 500。 ## 改动 1. **GET /cover-templates**:捕获 `OperationalError`/`ProgrammingError`,降级返回 `{"items": [], "total": 0}` + warning 日志 2. **POST/PUT/DELETE**:捕获同类异常,返回 503(封面模板服务暂不可用)而非 500 3. 新增 4 个错误处理单测(共 32 个 passed) ## 交付标准 - [x] staging API 异常时降级返回空列表/503 而非 500 - [x] 32 单测通过 + ruff lint 通过 - [x] CI 全绿后合入 develop 注意:本 PR 不直接执行 staging 数据库迁移,迁移会在 CI 部署时自动执行(`alembic upgrade head`)。
xiaoxia added 1 commit 2026-08-10 10:28:05 +08:00
fix: 封面模板 API 错误处理加固,表不存在时降级返回空列表
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 47s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 56s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m7s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m35s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m41s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
e5bfb0cefc
- GET /cover-templates 捕获 OperationalError/ProgrammingError,返回空列表+warning日志
- POST/PUT/DELETE 捕获同类异常,返回 503 而非 500
- 新增 4 个错误处理单元测试(32 passed)

🚀 预览环境已部署

项目 详情
PR号 #1329
预览链接 https://pr-1329.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1329 | | 预览链接 | [https://pr-1329.preview.xiaoxiajianji.com](https://pr-1329.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
Collaborator

【阻塞级判定】

  • 是否存在阻塞级问题:是
  • 阻塞级问题数量:2 个

📊 审查概览

  • 整体评价:需修改
  • 建议级问题数量:1 个

🔴 阻塞级问题(必须修复)

  1. [apps/api/app/api/routes/cover_templates.py: 36-47] 列表接口错误处理逻辑不一致

    • 问题类型:逻辑bug
    • 问题描述:list_cover_templates 接口在捕获到数据库异常时返回了 HTTP 200 状态码(通过返回 Response 对象隐式实现)和空列表,而 createupdatedelete 接口在相同情况下返回了 HTTP 503 状态码。这种不一致性会导致前端无法正确判断服务状态(误以为无数据而非服务不可用),同时掩盖了数据库故障,不利于监控和运维。
    • 修改建议:list_cover_templates 应与其他接口保持一致,在捕获到 OperationalErrorProgrammingError 时抛出 HTTPException(status_code=503),或者至少返回一个明确的错误状态码,而不是伪装成成功的空数据响应。
  2. [apps/api/app/api/routes/cover_templates.py: 102-111, 140-149] 更新与删除接口异常捕获范围不足

    • 问题类型:逻辑bug / 边界条件遗漏
    • 问题描述:在 update_cover_templatedelete_cover_template 中,try-except 块仅包裹了 repo.get(template_id)。如果 repo.get 成功(表存在),但后续的 repo.updaterepo.delete 操作因数据库连接断开、死锁等抛出 OperationalError,这些异常将不会被捕获,导致接口返回 500 错误。这违背了 PR 描述中“数据库表不可用时降级处理”的初衷,且与 create 接口(包裹了整个写操作)的行为不一致。
    • 修改建议:将 try-except 块的范围扩大,覆盖所有可能产生数据库交互的代码(包括 repo.updaterepo.delete),确保在数据库不可用时能统一返回 503。

💡 改进建议(不阻塞合并)

  1. [apps/api/app/api/routes/cover_templates.py] 代码重复与可维护性
    • 具体内容:四个接口中存在大量重复的 try-except (OperationalError, ProgrammingError) 逻辑。建议将此异常处理逻辑提取为 FastAPI 的 dependency 或装饰器,以减少代码重复并提高可维护性。

良好实践

  • 单元测试覆盖全面,针对 OperationalErrorProgrammingError 分别编写了测试用例,验证了降级逻辑。
  • 日志记录得当,在捕获异常时记录了详细的警告信息,便于排查问题。

格式检查通过 | 逻辑审查需修改 | 性能无问题


🤖 由 AI 代码审查机器人自动生成 | 2026-08-10 02:30:52 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:2 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:1 个 ### 🔴 阻塞级问题(必须修复) 1. **[apps/api/app/api/routes/cover_templates.py: 36-47] 列表接口错误处理逻辑不一致** - 问题类型:逻辑bug - 问题描述:`list_cover_templates` 接口在捕获到数据库异常时返回了 HTTP 200 状态码(通过返回 Response 对象隐式实现)和空列表,而 `create`、`update`、`delete` 接口在相同情况下返回了 HTTP 503 状态码。这种不一致性会导致前端无法正确判断服务状态(误以为无数据而非服务不可用),同时掩盖了数据库故障,不利于监控和运维。 - 修改建议:`list_cover_templates` 应与其他接口保持一致,在捕获到 `OperationalError` 或 `ProgrammingError` 时抛出 HTTPException(status_code=503),或者至少返回一个明确的错误状态码,而不是伪装成成功的空数据响应。 2. **[apps/api/app/api/routes/cover_templates.py: 102-111, 140-149] 更新与删除接口异常捕获范围不足** - 问题类型:逻辑bug / 边界条件遗漏 - 问题描述:在 `update_cover_template` 和 `delete_cover_template` 中,`try-except` 块仅包裹了 `repo.get(template_id)`。如果 `repo.get` 成功(表存在),但后续的 `repo.update` 或 `repo.delete` 操作因数据库连接断开、死锁等抛出 `OperationalError`,这些异常将不会被捕获,导致接口返回 500 错误。这违背了 PR 描述中“数据库表不可用时降级处理”的初衷,且与 `create` 接口(包裹了整个写操作)的行为不一致。 - 修改建议:将 `try-except` 块的范围扩大,覆盖所有可能产生数据库交互的代码(包括 `repo.update` 和 `repo.delete`),确保在数据库不可用时能统一返回 503。 ### 💡 改进建议(不阻塞合并) 1. **[apps/api/app/api/routes/cover_templates.py] 代码重复与可维护性** - 具体内容:四个接口中存在大量重复的 `try-except (OperationalError, ProgrammingError)` 逻辑。建议将此异常处理逻辑提取为 FastAPI 的 `dependency` 或装饰器,以减少代码重复并提高可维护性。 ### ✅ 良好实践 - 单元测试覆盖全面,针对 `OperationalError` 和 `ProgrammingError` 分别编写了测试用例,验证了降级逻辑。 - 日志记录得当,在捕获异常时记录了详细的警告信息,便于排查问题。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ✅ 性能无问题 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-10 02:30:52 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot added 1 commit 2026-08-10 10:30:52 +08:00
style: auto-format with black + isort + prettier [skip ci-format-check]
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 48s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m2s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m4s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m30s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m50s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m5s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 3m6s
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m46s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m46s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m55s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m25s
CI/CD Pipeline / CI Gate (pull_request) Successful in 14s
AI Code Review / AI Code Review (pull_request) Successful in 6m58s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 50s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m2s
2e93bf437c
auto-approve-bot approved these changes 2026-08-10 10:35:31 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-08-10 10:35:31 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
xiaoxia merged commit 0c6ec8995f into develop 2026-08-10 10:40:11 +08:00

🗑️ 预览环境已清理

PR #1329 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1329 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.