docs: add issue - MCP start_article_summary_job timeout but job actually runs
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
# [bug] MCP `start_article_summary_job` 超时但 job 实际执行了
|
||||
|
||||
## 问题描述
|
||||
|
||||
连续多个 `start_article_summary_job` 调用报 MCP 超时(-32001 Request timed out),但 job 实际执行了:
|
||||
|
||||
- `run_state.json` 显示 `status: failed`,`current_stage: generate_markdown`
|
||||
- job 目录正常生成,`run-state.json` 存在于 `outputs/freshrss/article_summary_jobs/<job-id>/`
|
||||
- `generate_markdown` 阶段实际执行过(有结果),但 MCP 响应没能发回来
|
||||
|
||||
## 根因分析
|
||||
|
||||
`server.py` 的 `start_article_summary_job` handler 用同步方式处理请求:
|
||||
|
||||
```python
|
||||
proc = subprocess.Popen(
|
||||
cmd,
|
||||
cwd=str(REPO_ROOT),
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
start_new_session=True,
|
||||
)
|
||||
# ← Popen 返回后,server 主进程在发送 stdio 响应前被阻塞
|
||||
return {
|
||||
"job_id": job_id,
|
||||
"status": "running",
|
||||
...
|
||||
} # ← 这里应该立即返回,但可能被某种同步操作卡住
|
||||
```
|
||||
|
||||
job 启动流程本身没问题(subprocess 确实被启动并执行了),问题出在 **MCP server 发送响应的环节**。
|
||||
|
||||
可能的阻塞点:
|
||||
1. `store.save()` 或 `store.finish_stage()` 涉及的磁盘锁
|
||||
2. stdio 响应的序列化或写入
|
||||
3. MCP server 的某种并发控制
|
||||
|
||||
## 修复方向
|
||||
|
||||
将 job 启动改造为真正的非阻塞模式:
|
||||
|
||||
- **方案 A(推荐):** 用后台线程/线程池(`concurrent.futures.ThreadPoolExecutor`)启动 job runner,主线程立即返回响应
|
||||
- **方案 B:** 改用纯异步模式,job 状态完全通过 `get_article_summary_job_status` 查询
|
||||
|
||||
## 正确处理(临时 workaround)
|
||||
|
||||
当 MCP 调用 `start_article_summary_job` 超时后,不应立即判定 job 失败:
|
||||
|
||||
1. 调用 `get_article_summary_job_status(job_id)` 查询真实状态
|
||||
2. 若返回 `status=running` 或 `run_state.json` 存在且 `status=running` → job 在跑,继续等待
|
||||
3. 若返回 `status=failed` → 查 `run_state.json` 的 `failed_stage` 和 `error_summary`
|
||||
|
||||
## 影响范围
|
||||
|
||||
- OpenClaw MCP 客户端调用 `start_article_summary_job`
|
||||
- 任何通过 stdio MCP 通道使用 article summary job 的场景
|
||||
|
||||
## 复现时间
|
||||
|
||||
2026-04-16
|
||||
Reference in New Issue
Block a user