fix(P0): 修复worker启动崩溃 - celery信号注册方式错误导致死循环重启 #538

Merged
auto-approve-bot merged 1 commits from fix/p0-worker-startup-crash into develop 2026-07-18 20:58:02 +08:00
Owner

问题

#535上线后worker启动即崩溃,死循环重启44次,生成任务完全不消费。

根因

_startup.py 中使用了 @celery_app.on_worker_ready.connect 注册信号,但 Celery 5.4.0 的 Celery app 对象没有 on_worker_ready 这个属性,导致导入模块时 AttributeError,worker启动直接崩。

修复

  • 改为从 celery.signals 导入 worker_ready 信号
  • 使用 @worker_ready.connect 注册
  • 删除没用的 on_after_configure 空钩子
  • 删除 celery_app 的 import

验证

  • 5个孤儿任务清理单元测试全绿
  • black / isort / ruff 全部通过
## 问题 #535上线后worker启动即崩溃,死循环重启44次,生成任务完全不消费。 ## 根因 `_startup.py` 中使用了 `@celery_app.on_worker_ready.connect` 注册信号,但 Celery 5.4.0 的 Celery app 对象没有 `on_worker_ready` 这个属性,导致导入模块时 AttributeError,worker启动直接崩。 ## 修复 - 改为从 `celery.signals` 导入 `worker_ready` 信号 - 使用 `@worker_ready.connect` 注册 - 删除没用的 `on_after_configure` 空钩子 - 删除 `celery_app` 的 import ## 验证 - 5个孤儿任务清理单元测试全绿 - black / isort / ruff 全部通过
xiaoxia added the bugbackendP0 labels 2026-07-18 20:24:00 +08:00

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #538 | | 预览链接 | [https://pr-538.preview.xiaoxiajianji.com](https://pr-538.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot approved these changes 2026-07-18 20:27:20 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-07-18 20:27:20 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
Collaborator

Auto merge failed after multiple 405 errors: PR may have conflicts or unresolved checks. Please review manually.

Auto merge failed after multiple 405 errors: PR may have conflicts or unresolved checks. Please review manually.
Collaborator

代码审查结果 - PR #538

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

  1. apps/api/app/api/routes/task_center.py 第103, 123行:API响应未使用新增的 updated_at 字段。

    • 问题描述:代码中 updated_at 仍然使用 task.completed_at or task.started_at or task.created_at 的回退逻辑,而没有直接使用本次 PR 新增的 task.updated_at 字段。这导致数据库层面的 updated_at 更新(如 onupdate 触发)无法正确反映给前端,违背了添加该字段的初衷。
    • 修改建议:直接使用 task.updated_at,即 updated_at=format_utc_datetime(task.updated_at)
  2. apps/worker/worker_app/tasks/generation.py 第1412-1420行:在任务执行流程中同步调用清理逻辑,存在严重性能隐患。

    • 问题描述:generate_video 是高频调用的异步任务。在每次任务开始时都调用 cleanup_orphan_tasks()(包含数据库查询和可能的更新操作),会显著增加任务延迟,给数据库造成不必要的压力。清理操作应该是低频的后台维护任务,不应阻塞业务流程。
    • 修改建议:移除此处的调用。孤儿任务清理应仅在 Worker 启动时(_startup.py)或通过 Celery Beat 定时任务执行。
  3. apps/worker/worker_app/tasks/_startup.py 第30-39行:数据库 Session 资源泄漏风险。

    • 问题描述:session = SessionLocal()try 块中创建,但 session.close() 也在 try 块中。如果 repo.cleanup_stale_running 或后续代码抛出异常,session.close() 将不会被执行,导致数据库连接泄漏。
    • 修改建议:使用 try...finally... 结构确保 Session 一定会被关闭,或者使用上下文管理器。
  4. packages/adapters/sqlalchemy_impl/generation_task_repository.py 第236-252行cleanup_stale_running 方法存在内存溢出(OOM)风险。

    • 问题描述:使用 .all() 将所有符合条件的记录加载到内存中,然后循环更新。如果存在大量孤儿任务(如数万条),会消耗大量内存,甚至导致 Worker 崩溃。
    • 修改建议:使用 SQLAlchemy 的 query(...).update(...) 进行批量更新,设置 synchronize_session=False,避免加载对象到内存。

💡 建议(1个可选)

  1. apps/api/app/api/routes/_helpers.py 第126-135行format_utc_datetime 函数对字符串类型的处理较为粗糙。
    • 具体内容:函数中 if isinstance(dt, str): return dt 直接返回了字符串。如果数据库某处意外返回了不带时区信息的字符串(如 "2023-01-01 00:00:00"),前端依然会解析错误。虽然 SQLAlchemy 通常返回 datetime 对象,但为了防御性编程,建议对字符串也进行简单的格式校验或补充 "Z" 后缀处理。

格式检查通过 | 逻辑审查需修改 | ⚠️ 建议关注性能


🤖 由 AI 代码审查机器人自动生成 | 2026-07-18 20:31:00 | 模型:

## 代码审查结果 - PR #538 ### ⚠️ 问题(4个需要修改) 1. **apps/api/app/api/routes/task_center.py 第103, 123行**:API响应未使用新增的 `updated_at` 字段。 - 问题描述:代码中 `updated_at` 仍然使用 `task.completed_at or task.started_at or task.created_at` 的回退逻辑,而没有直接使用本次 PR 新增的 `task.updated_at` 字段。这导致数据库层面的 `updated_at` 更新(如 `onupdate` 触发)无法正确反映给前端,违背了添加该字段的初衷。 - 修改建议:直接使用 `task.updated_at`,即 `updated_at=format_utc_datetime(task.updated_at)`。 2. **apps/worker/worker_app/tasks/generation.py 第1412-1420行**:在任务执行流程中同步调用清理逻辑,存在严重性能隐患。 - 问题描述:`generate_video` 是高频调用的异步任务。在每次任务开始时都调用 `cleanup_orphan_tasks()`(包含数据库查询和可能的更新操作),会显著增加任务延迟,给数据库造成不必要的压力。清理操作应该是低频的后台维护任务,不应阻塞业务流程。 - 修改建议:移除此处的调用。孤儿任务清理应仅在 Worker 启动时(`_startup.py`)或通过 Celery Beat 定时任务执行。 3. **apps/worker/worker_app/tasks/_startup.py 第30-39行**:数据库 Session 资源泄漏风险。 - 问题描述:`session = SessionLocal()` 在 `try` 块中创建,但 `session.close()` 也在 `try` 块中。如果 `repo.cleanup_stale_running` 或后续代码抛出异常,`session.close()` 将不会被执行,导致数据库连接泄漏。 - 修改建议:使用 `try...finally...` 结构确保 Session 一定会被关闭,或者使用上下文管理器。 4. **packages/adapters/sqlalchemy_impl/generation_task_repository.py 第236-252行**:`cleanup_stale_running` 方法存在内存溢出(OOM)风险。 - 问题描述:使用 `.all()` 将所有符合条件的记录加载到内存中,然后循环更新。如果存在大量孤儿任务(如数万条),会消耗大量内存,甚至导致 Worker 崩溃。 - 修改建议:使用 SQLAlchemy 的 `query(...).update(...)` 进行批量更新,设置 `synchronize_session=False`,避免加载对象到内存。 ### 💡 建议(1个可选) 1. **apps/api/app/api/routes/_helpers.py 第126-135行**:`format_utc_datetime` 函数对字符串类型的处理较为粗糙。 - 具体内容:函数中 `if isinstance(dt, str): return dt` 直接返回了字符串。如果数据库某处意外返回了不带时区信息的字符串(如 "2023-01-01 00:00:00"),前端依然会解析错误。虽然 SQLAlchemy 通常返回 datetime 对象,但为了防御性编程,建议对字符串也进行简单的格式校验或补充 "Z" 后缀处理。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-18 20:31:00 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
xiaoxia added 1 commit 2026-07-18 20:51:27 +08:00
fix(P0): 修复worker启动崩溃 - celery信号注册方式错误导致死循环重启
CI Build & Deploy Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Production (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI Build & Deploy Pipeline / Production Browser E2E (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging API Integration Tests (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Failing after 16s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 30s
AI Code Review / AI Code Review (pull_request) Failing after 35s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m3s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 2m0s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m45s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 3m2s
Auto Approve CI PRs / Auto Approve on CI Green (pull_request) Successful in 5m36s
Auto Merge CI PRs / Auto Merge on CI Green + Approved (pull_request) Successful in 6m34s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 17s
b4aa6ee4ee
xiaoxia force-pushed fix/p0-worker-startup-crash from 285c604994 to b4aa6ee4ee 2026-07-18 20:51:27 +08:00 Compare
auto-approve-bot merged commit 229b25514d into develop 2026-07-18 20:58:02 +08:00
auto-approve-bot deleted branch fix/p0-worker-startup-crash 2026-07-18 20:58:02 +08:00

🗑️ 预览环境已清理

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

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

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