Files
reader/plans/freshrss-pipeline-async-job-plan.md
T

230 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FreshRSS 主日报异步 job 方案
## 背景
当前 `run_freshrss_openclaw_pipeline` 虽然已经作为正式 MCP workflow 入口存在,但执行模型仍是**同步 MCP 调用**。这会带来几个现实问题:
1. OpenClaw / MCP wrapper 存在超时风险,尤其是 5-10 篇的正式日报批次。
2. wrapper timeout 与真实 run 是否已落地,容易出现语义分离。
3. 当前已有 `run-state.json`、`get_run_status`、`get_run_report`、`get_delivery_payload`,但**启动层**仍然是同步调用,不利于正式生产链路稳定运行。
4. 单篇总结已经验证了“最小 async job + 轮询状态 + 读取结果”模型可行,主日报 run 应收敛到同一套运行模式。
## 目标
将 FreshRSS 主日报 run 改造成与 article-summary 类似的**最小真异步 job**:
- 启动即返回 `job_id`
- 真正执行由后台子进程完成
- 状态可轮询
- 成功后可读取结构化结果
- 业务逻辑继续复用既有 `run_freshrss_pipeline(...)`
- 不推翻现有 run-state / result query 能力
## 非目标
本阶段不做:
- 分布式任务队列
- 多 worker 调度
- 任意 stage 的后台恢复编排
- 并发控制中心
- 主流程与 article-summary job 的通用抽象框架一次性大重构
先做最小可用。
## 设计原则
1. **启动层异步化,执行核心不重写**
- `run_freshrss_pipeline(...)` 继续是主业务逻辑真相。
- async job 只负责启动、状态持久化、结果回读。
2. **run truth 与 job truth 分层**
- job truth:这次异步任务有没有启动、运行到哪一步、是否成功。
- run truth:真正的 freshrss workflow 输出与 `run-state.json`。
3. **OpenClaw 正式生产默认改为 async start path**
- 启动走 async job
- 状态和结果优先先看 job
- 真正业务产物仍由现有 run 查询工具承接
4. **与 article-summary job 尽量同构**
- 目录结构
- `run-state.json` / `input.json` / `result.json` / `job-report.json`
- 后台 runner 脚本
## 拟新增能力
### MCP tools
新增 3 个工具:
- `start_freshrss_pipeline_job`
- `get_freshrss_pipeline_job_status`
- `get_freshrss_pipeline_job_result`
### job 目录
固定目录:
`outputs/freshrss/pipeline_jobs/<job_id>/`
至少包含:
- `run-state.json`
- `input.json`
- `result.json`(成功时)
- `job-report.json`
### 执行模型
- `start_freshrss_pipeline_job` 写入 input + 初始化 job state
- 后台 `subprocess.Popen(...)` 启动 runner
- runner 内部调用 `run_freshrss_pipeline(...)`
- 成功后把 `run_id`、核心产物路径、关键计数写入 `result.json`
## job 输入参数
与现有 `run_freshrss_openclaw_pipeline` 尽量对齐:
- `limit`
- `mark_read`
- `include_read`
- `debug_artifacts`
- `continuation`
- `timeout_seconds`
- `max_retries`
- `stream_id`
- `api_base_url`
- `username`
- `api_password`
- `llm_api_key`
- `llm_model`
- `llm_api_url`
- `context`
- `run_id`
- `date_value`
- `output_dir`
- `include_item_reports`
## 返回语义
### start
返回:
- `job_id`
- `workflow`
- `run_type`
- `status=running`
- `output_dir`
- `message`
### status
返回:
- `job_id`
- `status`
- `current_stage`
- `started_at` / `updated_at` / `finished_at`
- `progress`
- `artifacts`
- `error_summary`
- 若主 run 已创建,可附带 `linked_run_id`
### result
成功时返回:
- `job_id`
- `status=success`
- `run_id`
- `delivery_output`
- `report_output`
- `digest_brief_output`
- `pulled_count`
- `delivered_count`
- `marked_read_count`
- `artifact`
- `result`
## stages 建议
最小 job stages:
1. `prepare_job`
2. `load_input`
3. `run_pipeline`
4. `write_result`
其中 `run_pipeline` 内部仍由现有 freshrss workflow 自己写它的 run-state。
## 与现有同步入口的关系
### 保留
`run_freshrss_openclaw_pipeline` 暂时保留,作为:
- debug / light path
- 本地调试工具
- 向后兼容路径
### 正式语义调整
文档与 OpenClaw handoff 中,主日报正式生产默认启动入口改为:
- `start_freshrss_pipeline_job`
同步入口降级为:
- debug / fallback
- 小批量验证
## OpenClaw 编排建议
新的推荐路径:
1. `start_freshrss_pipeline_job`
2. `get_freshrss_pipeline_job_status`
3. 成功后 `get_freshrss_pipeline_job_result`
4. 后续仍用:
- `get_run_status`
- `get_delivery_payload`
- `get_run_report`
- `list_run_artifacts`
## 风险点
1. **job 成功但 run 部分失败**
- 允许,job 结果应以真实 `run_freshrss_pipeline(...)` 返回为准。
- `run_id` + `report_output` 仍是最终真相。
2. **runner 崩溃但来不及写 result**
- 需保证 `job-report.json` 至少能写下失败摘要。
3. **重复状态源导致混淆**
- 文档必须明确:
- job state 管“启动任务”
- run state 管“业务工作流真相”
4. **同步 / 异步双入口长期漂移**
- 必须要求 async job 内部直接复用 `run_freshrss_pipeline(...)`
- 禁止再实现一套平行主流程
## 验收标准
1. 能通过 MCP 启动一个主日报 async job 并立即返回 `job_id`
2. 能轮询到 `running -> success/failed`
3. 成功后 `result.json` 含 `run_id` 与核心产物路径
4. 对应 run 仍能通过既有 `get_run_status` / `get_run_report` / `get_delivery_payload` 正常读取
5. README / handoff / TODO / plans 同步更新
## 建议实施顺序
1. 复制 article-summary job 骨架到 freshrss pipeline job
2. 新增 runner 脚本
3. server.py 暴露 3 个新工具
4. 补 query/result 读法
5. 更新 README / handoff
6. 将 TODO 主任务切到“主日报 async job”