5.5 KiB
5.5 KiB
FreshRSS 主日报异步 job 方案
背景
当前 run_freshrss_openclaw_pipeline 虽然已经作为正式 MCP workflow 入口存在,但执行模型仍是同步 MCP 调用。这会带来几个现实问题:
- OpenClaw / MCP wrapper 存在超时风险,尤其是 5-10 篇的正式日报批次。
- wrapper timeout 与真实 run 是否已落地,容易出现语义分离。
- 当前已有
run-state.json、get_run_status、get_run_report、get_delivery_payload,但启动层仍然是同步调用,不利于正式生产链路稳定运行。 - 单篇总结已经验证了“最小 async job + 轮询状态 + 读取结果”模型可行,主日报 run 应收敛到同一套运行模式。
目标
将 FreshRSS 主日报 run 改造成与 article-summary 类似的最小真异步 job:
- 启动即返回
job_id - 真正执行由后台子进程完成
- 状态可轮询
- 成功后可读取结构化结果
- 业务逻辑继续复用既有
run_freshrss_pipeline(...) - 不推翻现有 run-state / result query 能力
非目标
本阶段不做:
- 分布式任务队列
- 多 worker 调度
- 任意 stage 的后台恢复编排
- 并发控制中心
- 主流程与 article-summary job 的通用抽象框架一次性大重构
先做最小可用。
设计原则
-
启动层异步化,执行核心不重写
run_freshrss_pipeline(...)继续是主业务逻辑真相。- async job 只负责启动、状态持久化、结果回读。
-
run truth 与 job truth 分层
- job truth:这次异步任务有没有启动、运行到哪一步、是否成功。
- run truth:真正的 freshrss workflow 输出与
run-state.json。
-
OpenClaw 正式生产默认改为 async start path
- 启动走 async job
- 状态和结果优先先看 job
- 真正业务产物仍由现有 run 查询工具承接
-
与 article-summary job 尽量同构
- 目录结构
run-state.json/input.json/result.json/job-report.json- 后台 runner 脚本
拟新增能力
MCP tools
新增 3 个工具:
start_freshrss_pipeline_jobget_freshrss_pipeline_job_statusget_freshrss_pipeline_job_result
job 目录
固定目录:
outputs/freshrss/pipeline_jobs/<job_id>/
至少包含:
run-state.jsoninput.jsonresult.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 尽量对齐:
limitmark_readinclude_readdebug_artifactscontinuationtimeout_secondsmax_retriesstream_idapi_base_urlusernameapi_passwordllm_api_keyllm_modelllm_api_urlcontextrun_iddate_valueoutput_dirinclude_item_reports
返回语义
start
返回:
job_idworkflowrun_typestatus=runningoutput_dirmessage
status
返回:
job_idstatuscurrent_stagestarted_at/updated_at/finished_atprogressartifactserror_summary- 若主 run 已创建,可附带
linked_run_id
result
成功时返回:
job_idstatus=successrun_iddelivery_outputreport_outputdigest_brief_outputpulled_countdelivered_countmarked_read_countartifactresult
stages 建议
最小 job stages:
prepare_jobload_inputrun_pipelinewrite_result
其中 run_pipeline 内部仍由现有 freshrss workflow 自己写它的 run-state。
与现有同步入口的关系
保留
run_freshrss_openclaw_pipeline 暂时保留,作为:
- debug / light path
- 本地调试工具
- 向后兼容路径
正式语义调整
文档与 OpenClaw handoff 中,主日报正式生产默认启动入口改为:
start_freshrss_pipeline_job
同步入口降级为:
- debug / fallback
- 小批量验证
OpenClaw 编排建议
新的推荐路径:
start_freshrss_pipeline_jobget_freshrss_pipeline_job_status- 成功后
get_freshrss_pipeline_job_result - 后续仍用:
get_run_statusget_delivery_payloadget_run_reportlist_run_artifacts
风险点
-
job 成功但 run 部分失败
- 允许,job 结果应以真实
run_freshrss_pipeline(...)返回为准。 run_id+report_output仍是最终真相。
- 允许,job 结果应以真实
-
runner 崩溃但来不及写 result
- 需保证
job-report.json至少能写下失败摘要。
- 需保证
-
重复状态源导致混淆
- 文档必须明确:
- job state 管“启动任务”
- run state 管“业务工作流真相”
- 文档必须明确:
-
同步 / 异步双入口长期漂移
- 必须要求 async job 内部直接复用
run_freshrss_pipeline(...) - 禁止再实现一套平行主流程
- 必须要求 async job 内部直接复用
验收标准
- 能通过 MCP 启动一个主日报 async job 并立即返回
job_id - 能轮询到
running -> success/failed - 成功后
result.json含run_id与核心产物路径 - 对应 run 仍能通过既有
get_run_status/get_run_report/get_delivery_payload正常读取 - README / handoff / TODO / plans 同步更新
建议实施顺序
- 复制 article-summary job 骨架到 freshrss pipeline job
- 新增 runner 脚本
- server.py 暴露 3 个新工具
- 补 query/result 读法
- 更新 README / handoff
- 将 TODO 主任务切到“主日报 async job”