test(wave94): extract media_validation domain module + 70 unit tests #957

Closed
xiaoxia wants to merge 0 commits from test/wave94-media-validation into develop
Owner

变更内容

  • 从 ingest.py 抽取媒体校验纯逻辑到独立领域模块 packages/domain/media_validation.py
  • 包含 safe_parse_fps: FPS 分数格式安全解析
  • 包含 is_valid_media: 视频/音频/图片有效性校验
  • 包含常量: MIN_VIDEO/AUDIO/IMAGE_FILE_SIZE + SUPPORTED_VIDEO_CODECS
  • 新增 70 个单元测试,完整覆盖纯逻辑
  • ingest.py 瘦身: 424行 → 340行(-84行,-20%)
  • 向后兼容:私有方法别名保留,原 25 个测试全绿

测试覆盖分布

  • safe_parse_fps: 18 tests(基础格式/边界/异常)
  • 常量验证: 11 tests(文件大小常量 + 编码白名单)
  • is_valid_media 视频: 17 tests
  • is_valid_media 音频: 9 tests
  • is_valid_media 图片: 11 tests
  • 未知类型 + 类型边界: 5 tests

测试结果

本地 95 passed (70 新 + 25 原)

## 变更内容 - 从 ingest.py 抽取媒体校验纯逻辑到独立领域模块 `packages/domain/media_validation.py` - 包含 safe_parse_fps: FPS 分数格式安全解析 - 包含 is_valid_media: 视频/音频/图片有效性校验 - 包含常量: MIN_VIDEO/AUDIO/IMAGE_FILE_SIZE + SUPPORTED_VIDEO_CODECS - 新增 70 个单元测试,完整覆盖纯逻辑 - ingest.py 瘦身: 424行 → 340行(-84行,-20%) - 向后兼容:私有方法别名保留,原 25 个测试全绿 ## 测试覆盖分布 - safe_parse_fps: 18 tests(基础格式/边界/异常) - 常量验证: 11 tests(文件大小常量 + 编码白名单) - is_valid_media 视频: 17 tests - is_valid_media 音频: 9 tests - is_valid_media 图片: 11 tests - 未知类型 + 类型边界: 5 tests ## 测试结果 本地 95 passed (70 新 + 25 原)
xiaoxia force-pushed test/wave94-media-validation from 1724477ee4 to 287d4794b1 2026-07-26 20:11:14 +08:00 Compare

🚀 预览环境已部署

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

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

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

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

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

代码审查结果 - PR #957

⚠️ 问题(2个需要修改)

  1. packages/domain/media_validation.py 第89行、99行:类型转换缺乏容错性,存在崩溃风险。

    • 问题描述:代码中使用 int(metadata.get("size_bytes", 0))int(metadata.get(...)) 进行强制转换。如果元数据中的值为 None 或空字符串 ""(虽然 get 有默认值,但如果 Key 存在且 Value 为 None,则不会使用默认值),int() 会抛出 TypeErrorValueError。虽然单元测试中覆盖了 None 并预期抛出异常,但在生产环境的 ingest 流程中,验证函数应具备防御性,应返回 False 判定无效,而不是导致任务崩溃。
    • 修改建议:使用 int(val or 0) 或辅助函数进行安全转换,确保异常数据被识别为“无效媒体”而非“程序错误”。
  2. packages/domain/media_validation.py 第95-97行:移除了关键日志记录,导致可观测性降低。

    • 问题描述:原代码在检测到非白名单视频编码时会记录 logger.info,用于追踪和调试非常规格式的视频文件。重构后的代码移除了该日志,仅保留注释“调用方负责日志”,但调用方 ingest.py 中的 extract_media_metadata 并未变更以补充此日志。这导致系统无法再记录此类信息,增加了排查问题的难度。
    • 修改建议:在 media_validation.py 中恢复日志记录(需注入 logger),或者修改 ingest.py 中的调用逻辑,在调用 _is_valid_media 后补充日志对非白名单编码的记录。

💡 建议(1个可选)

  1. packages/domain/media_validation.py 第71行:帧率(FPS)允许负数缺乏物理意义。
    • 具体内容:safe_parse_fps 函数当前允许解析出负值(如 -30),并在测试中验证了这一点。然而,帧率在物理上不可能为负数。负值可能会影响下游依赖此函数进行帧数计算(如 duration * fps)的逻辑,导致负的帧数。
    • 建议:在函数返回前增加校验,如果结果小于 0,则返回 0.0。

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


🤖 由 AI 代码审查机器人自动生成 | 2026-07-26 17:20:08 | 模型:

## 代码审查结果 - PR #957 ### ⚠️ 问题(2个需要修改) 1. **packages/domain/media_validation.py 第89行、99行**:类型转换缺乏容错性,存在崩溃风险。 - 问题描述:代码中使用 `int(metadata.get("size_bytes", 0))` 和 `int(metadata.get(...))` 进行强制转换。如果元数据中的值为 `None` 或空字符串 `""`(虽然 `get` 有默认值,但如果 Key 存在且 Value 为 None,则不会使用默认值),`int()` 会抛出 `TypeError` 或 `ValueError`。虽然单元测试中覆盖了 `None` 并预期抛出异常,但在生产环境的 `ingest` 流程中,验证函数应具备防御性,应返回 `False` 判定无效,而不是导致任务崩溃。 - 修改建议:使用 `int(val or 0)` 或辅助函数进行安全转换,确保异常数据被识别为“无效媒体”而非“程序错误”。 2. **packages/domain/media_validation.py 第95-97行**:移除了关键日志记录,导致可观测性降低。 - 问题描述:原代码在检测到非白名单视频编码时会记录 `logger.info`,用于追踪和调试非常规格式的视频文件。重构后的代码移除了该日志,仅保留注释“调用方负责日志”,但调用方 `ingest.py` 中的 `extract_media_metadata` 并未变更以补充此日志。这导致系统无法再记录此类信息,增加了排查问题的难度。 - 修改建议:在 `media_validation.py` 中恢复日志记录(需注入 logger),或者修改 `ingest.py` 中的调用逻辑,在调用 `_is_valid_media` 后补充日志对非白名单编码的记录。 ### 💡 建议(1个可选) 1. **packages/domain/media_validation.py 第71行**:帧率(FPS)允许负数缺乏物理意义。 - 具体内容:`safe_parse_fps` 函数当前允许解析出负值(如 `-30`),并在测试中验证了这一点。然而,帧率在物理上不可能为负数。负值可能会影响下游依赖此函数进行帧数计算(如 `duration * fps`)的逻辑,导致负的帧数。 - 建议:在函数返回前增加校验,如果结果小于 0,则返回 0.0。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ✅ 性能无恙 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-26 17:20:08 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
xiaoxia force-pushed test/wave94-media-validation from 05852fb050 to 5289e427e2 2026-07-27 18:55:47 +08:00 Compare
xiaoxia closed this pull request 2026-07-27 19:49:00 +08:00

🗑️ 预览环境已清理

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

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

🗑️ **预览环境已清理** PR #957 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Some checks are pending
CI/CD Pipeline / Check if frontend-only change (push) Has been cancelled
CI/CD Pipeline / Validate - Code Quality (push) Has been cancelled
CI/CD Pipeline / Validate - Type Check (mypy) (push) Has been cancelled
CI/CD Pipeline / Validate - Migration (alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Failing after 0s
PR Automation / Auto Approve on CI Green (pull_request) Failing after 0s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 0s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Failing after 0s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m33s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 48s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Failing after 1s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 0s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Failing after 1s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Failing after 0s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 0s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 0s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 0s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 0s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 10m44s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m58s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m54s
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 / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Failing after 0s

Pull request closed

Sign in to join this conversation.