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

5.5 KiB
Raw Permalink Blame History

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”