fix: MediaKit 重试逻辑 + TimeInterval默认策略 + 错误日志增强 #1227

Merged
xiaoxia merged 3 commits from fix/mediakit-retry-reliability-issue1209 into develop 2026-08-03 13:51:28 +08:00
Owner

问题

MediaKit 服务端偶发 signal: killed (OOM) 导致视频理解/抽帧失败,降级后丢失了智能编排能力。

修复

1. 自动重试逻辑

  • extract_framesanalyze_videos 新增 max_retries 参数(默认 1 次重试)
  • 仅对可重试错误(signal: killedInternalErrorOOM)触发重试,间隔 2s
  • 不可重试错误(如 model timeout)直接返回,不浪费等待时间

2. 默认抽帧策略改为 TimeInterval

  • extract_frames 默认策略从 SceneChangeTimeInterval
  • SceneChange 对高分辨率视频容易 OOM,TimeInterval 更稳定
  • AI 封面(ai_service.py)同步改为 TimeInterval

3. 错误日志增强

  • 失败日志包含完整 task_id + error + error_node
  • 新增 _with_error 轮询方法,返回 (result, error_msg) 二元组
  • 重试决策点记录 retryable 标记,方便排查

测试

  • 新增 16 个单元测试(重试逻辑、策略判断、日志验证)
  • 全部 46 个 MediaKit 相关测试通过
## 问题 MediaKit 服务端偶发 `signal: killed` (OOM) 导致视频理解/抽帧失败,降级后丢失了智能编排能力。 ## 修复 ### 1. 自动重试逻辑 - `extract_frames` 和 `analyze_videos` 新增 `max_retries` 参数(默认 1 次重试) - 仅对可重试错误(`signal: killed`、`InternalError`、`OOM`)触发重试,间隔 2s - 不可重试错误(如 model timeout)直接返回,不浪费等待时间 ### 2. 默认抽帧策略改为 TimeInterval - `extract_frames` 默认策略从 `SceneChange` → `TimeInterval` - SceneChange 对高分辨率视频容易 OOM,TimeInterval 更稳定 - AI 封面(ai_service.py)同步改为 TimeInterval ### 3. 错误日志增强 - 失败日志包含完整 `task_id` + `error` + `error_node` - 新增 `_with_error` 轮询方法,返回 `(result, error_msg)` 二元组 - 重试决策点记录 retryable 标记,方便排查 ## 测试 - 新增 16 个单元测试(重试逻辑、策略判断、日志验证) - 全部 46 个 MediaKit 相关测试通过
xiaoxia added 3 commits 2026-08-03 13:42:22 +08:00
feat: add test_mediakit_retry.py
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 / ACR Image Cleanup (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 / Check if frontend-only change (pull_request) Successful in 37s
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 - Migration (alembic) (pull_request) Successful in 49s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 54s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m21s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m37s
AI Code Review / AI Code Review (pull_request) Failing after 2m17s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m52s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m52s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 3m0s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m32s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m36s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 7m38s
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 / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 39s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 54s
cf7b5a62a8

🚀 预览环境已部署

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

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

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

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

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

【阻塞级判定】

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

📊 审查概览

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

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

  1. [packages/shared/mediakit_client.py: 162-163] 视频理解任务超时时间设置过短
    • 问题类型:逻辑bug
    • 问题描述:analyze_videos 方法的 poll_interval 从 3.0 改为 2.0,max_poll_attempts 从 60 改为 15。这导致总超时时间从 180秒(3分钟)骤降为 30秒。视频理解(AI分析)通常属于耗时任务,30秒的超时时间极短,极易导致正常请求因处理时间稍长而误报为超时失败。
    • 修改建议:核实修改意图。如果是误操作,建议恢复原值或调整为更合理的时长(如至少 60-120秒)。extract_frames 的超时时间为 60秒(2.0*30),视频理解的耗时通常不应低于抽帧。

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

  1. [packages/shared/mediakit_client.py: 396] 轮询异常处理会绕过重试机制

    • 具体内容:在 _poll_task_result_with_error_poll_video_understand_result_with_error 方法中,except Exception 捕获异常后会记录日志并 sleep,然后继续循环。这会消耗 max_poll_attempts 次数。如果因网络抖动导致多次异常,最终会返回“超时”错误。而外部重试逻辑判断“超时”字符串为不可重试错误(_is_retryable_error 返回 False),从而导致任务直接失败,无法利用 max_retries 进行重试。建议将异常信息传递出去,或者在超时错误信息中区分是“处理超时”还是“网络异常”。
  2. [packages/shared/mediakit_client.py: 26] 错误关键词匹配存在误报风险

    • 具体内容:_RETRYABLE_ERROR_KEYWORDS 中包含 "OOM"。该字符串较短,可能匹配到非预期的单词(如 "BOOM", "ROOM")。虽然概率较低,但建议使用更精确的关键词如 " out of memory "(带空格)或 "memory oom",以避免误判。
  3. [packages/shared/mediakit_client.py: 88-119] 重复代码

    • 具体内容:extract_framesanalyze_videos 中的重试循环逻辑(for attempt in range...)几乎完全一致。建议提取一个通用的重试装饰器或辅助方法(如 _execute_with_retry),以减少代码重复,提高可维护性。

良好实践

  • 新增了单元测试 test_mediakit_retry.py,覆盖了重试逻辑、错误分类和默认策略,测试覆盖度较好。
  • 引入 _is_retryable_error 明确区分了可重试与不可重试错误,避免了盲目重试。
  • 保留了旧版本的轮询方法(_poll_task_result)以兼容可能的旧调用,向后兼容性处理得当。

🤖 由 AI 代码审查机器人自动生成 | 2026-08-03 05:44:39 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:1 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:3 个 ### 🔴 阻塞级问题(必须修复) 1. **[packages/shared/mediakit_client.py: 162-163] 视频理解任务超时时间设置过短** - 问题类型:逻辑bug - 问题描述:`analyze_videos` 方法的 `poll_interval` 从 3.0 改为 2.0,`max_poll_attempts` 从 60 改为 15。这导致总超时时间从 180秒(3分钟)骤降为 30秒。视频理解(AI分析)通常属于耗时任务,30秒的超时时间极短,极易导致正常请求因处理时间稍长而误报为超时失败。 - 修改建议:核实修改意图。如果是误操作,建议恢复原值或调整为更合理的时长(如至少 60-120秒)。`extract_frames` 的超时时间为 60秒(2.0*30),视频理解的耗时通常不应低于抽帧。 ### 💡 改进建议(不阻塞合并) 1. **[packages/shared/mediakit_client.py: 396] 轮询异常处理会绕过重试机制** - 具体内容:在 `_poll_task_result_with_error` 和 `_poll_video_understand_result_with_error` 方法中,`except Exception` 捕获异常后会记录日志并 `sleep`,然后继续循环。这会消耗 `max_poll_attempts` 次数。如果因网络抖动导致多次异常,最终会返回“超时”错误。而外部重试逻辑判断“超时”字符串为不可重试错误(`_is_retryable_error` 返回 False),从而导致任务直接失败,无法利用 `max_retries` 进行重试。建议将异常信息传递出去,或者在超时错误信息中区分是“处理超时”还是“网络异常”。 2. **[packages/shared/mediakit_client.py: 26] 错误关键词匹配存在误报风险** - 具体内容:`_RETRYABLE_ERROR_KEYWORDS` 中包含 `"OOM"`。该字符串较短,可能匹配到非预期的单词(如 "BOOM", "ROOM")。虽然概率较低,但建议使用更精确的关键词如 `" out of memory "`(带空格)或 `"memory oom"`,以避免误判。 3. **[packages/shared/mediakit_client.py: 88-119] 重复代码** - 具体内容:`extract_frames` 和 `analyze_videos` 中的重试循环逻辑(`for attempt in range...`)几乎完全一致。建议提取一个通用的重试装饰器或辅助方法(如 `_execute_with_retry`),以减少代码重复,提高可维护性。 ### ✅ 良好实践 - 新增了单元测试 `test_mediakit_retry.py`,覆盖了重试逻辑、错误分类和默认策略,测试覆盖度较好。 - 引入 `_is_retryable_error` 明确区分了可重试与不可重试错误,避免了盲目重试。 - 保留了旧版本的轮询方法(`_poll_task_result`)以兼容可能的旧调用,向后兼容性处理得当。 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-03 05:44:39 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
xiaoxia merged commit 3e24f8de4a into develop 2026-08-03 13:51:28 +08:00
xiaoxia deleted branch fix/mediakit-retry-reliability-issue1209 2026-08-03 13:51:28 +08:00

🗑️ 预览环境已清理

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

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

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