6.5 KiB
6.5 KiB
架构设计与需求文档:RSSPipe
- 核心需求概述 本系统旨在构建一个针对单用户场景的 高度可扩展、本地优先(Local-First)且端到端加密的 RSS 网关客户端(PWA)。它不仅具备传统 RSS 的订阅与阅读功能,更通过事件驱动的规则引擎,深度集成 AI 能力。 关键特性要求:
- 本地优先 (Local-First PWA):核心数据存储与业务流转在客户端(浏览器环境)完成,支持离线访问。
- 端到端加密 (E2EE):数据在落盘或同步前必须在客户端加密,保证绝对隐私。
- 事件驱动的规则引擎 (Rules Engine):支持类似 Gmail Filter 的 Trigger-Condition-Action 机制。
- 防死循环与状态隔离 (DAG & CQRS):严格拆分 Feed 生命周期,分离单实体(Single-Entity)富化逻辑与多实体(Multi-Entity)聚合逻辑,彻底杜绝规则循环执行。
- 无缝旁路扩展 (Plugin/RPC):通过定义统一的“增量 Patch”通信契约,支持用 TS 编写本地 Plugin,或通过 gRPC/Connect 调用外部 Go/Python 的 AI 节点。
- 无预设动态 Schema:Feed 的附加数据(如 AI 摘要、评分、TTS 音频等)不硬编码在数据模型中,而是通过 JSON 增量合并。
- 遥测与反馈循环 (Telemetry):采集阅读行为(驻留时长、可见字数比),为下游 AI 模型或动态权重系统提供微调依据。
- 核心架构视图
- 核心数据模型 (Data Schema) 系统采用 Core (不可变主键) + Metadata (可变 JSONB) 的模式。 // 核心路由与索引字段(关系型特征) interface FeedCore { id: string; // 唯一标识符,基于 url + timestamp 哈希 url: string; // 原始链接 sourceId: string; // 订阅源 ID timestamp: number; // 抓取/发布时间戳 title: string; content: string; // 清洗后的纯文本/Markdown }
// 变长扩展数据(无预设 Schema) interface FeedMetadata { isRead: boolean; tags: string[]; // 标签集合 aiSummary?: string; // AI 摘要 ttsUrl?: string; // 语音合成链接 score?: number; // 推荐分数 [key: string]: any; // 其他外部 Plugin 注入的动态字段 }
// 数据库实际存储结构(明文态) interface LocalFeedEntry extends FeedCore { metadata: FeedMetadata; }
- 生命周期与规则引擎设计 (DAG Rule Engine) 为了防止死循环,Feed 的处理被严格限制在一个单向流动的流水线中。 4.1 生命周期的四个阶段 (Phases)
- Ingestion (摄入期):从远程 XML 拉取数据,使用 rss-parser 解析,使用 @mozilla/readability 提取纯正文。
- Enrichment (丰富期):单 Feed 事件的主战场。在此阶段,系统调用配置好的 Plugin(本地或远程),获取摘要、打分等元数据。
- Aggregation (聚合期):批处理的主战场。由独立的调度器(基于 RxJS)监听数据库写入操作,当符合特定条件的 Feed 数量达到阈值,触发聚合 Action(如生成周报)。
- Action (动作期):数据的最终落盘加密存储,以及触发 UI 层的渲染与系统通知。 4.2 统一 Plugin 接口契约 (Plugin Interface Protocol) 无论是前端本地的 TypeScript 函数,还是远端的 Go 语言 gRPC 服务,都必须遵循以下契约进行通信,强制使用 JSON Patch,禁止外部服务直接覆写完整 Feed 数据。 // 输入契约 (发送给 Plugin 的数据) interface PluginInput { eventId: string; phase: "enrichment" | "aggregation"; feedSnapshot: Readonly; feedMetadata: Readonly; triggerReason: string; }
// 输出契约 (Plugin 返回给主系统的指令) interface PluginOutput { action: "merge_metadata" | "drop_feed" | "none"; metadataPatch?: { $set?: Record<string, any>; // 覆写字段,如 { aiSummary: "..." } $push?: Record<string, any[]>; // 追加数组元素,如 { tags: ["tech"] } }; }
4.3 规则防死锁机制 在添加或修改 Rule 时,运行拓扑排序(Topological Sort)引擎,验证 Trigger 和 Action 之间是否存在循环依赖,存在则拒绝保存配置。 5. 里程碑拆解与模块化实现方案 Milestone 1: 本地基础设施 (Local-First Base)
- 任务目标:搭建基础 PWA 框架,实现端到端加密与基础数据读写。
- 关键技术栈:Vite + React, Dexie.js (IndexedDB), Web Crypto API。
- 核心模块:
- DB 层:基于 Dexie.js 定义本地表结构,只允许应用层通过统一的 Service 读写。
- 加密拦截器:数据写入 IndexedDB 前进行 AES-GCM 加密,读取时解密,确保本地离线数据的安全性。
- 基础 Parser:实现对 RSS 源的拉取和 @mozilla/readability 的正文清洗。 Milestone 2: 单 Feed 规则引擎与本地 Plugin (Core Engine)
- 任务目标:实现生命周期流水线与 Enrichment 阶段的核心逻辑。
- 关键技术栈:RxJS。
- 核心模块:
- 生命周期 Event Bus:基于 RxJS Subject 创建事件总线,控制数据流从 Ingestion 向下流转。
- Plugin 调度中心:根据用户配置的 Rules,将数据 Snapshot 传递给对应的本地 TS 函数,获取 Patch 并执行安全合并(Lodash merge 等效逻辑)。
- DAG 校验器:实现并集成拓扑排序算法,验证用户配置。 Milestone 3: 旁路扩展层 (Remote RPC & Extensibility)
- 任务目标:实现外部 Go/Python AI 控制器的接入。
- 关键技术栈:Connect-RPC (@connectrpc/connect-web), Protobuf。
- 核心模块:
- 契约生成:使用 Protobuf 将 PluginInput 和 PluginOutput 标准化,生成两端的接口代码。
- RPC 适配器:在前端 Rules Engine 中编写一个特殊的 Plugin Adapter,遇到远程规则时,通过 Connect 将数据发往 Go 后端服务,并等待返回 JSON Patch。
- 动态 UI 渲染器:重构阅读页面,使其不再依赖硬编码字段,而是根据 Metadata 动态挂载组件(如检测到 ttsUrl 挂载播放器)。 Milestone 4: 遥测与批量聚合处理 (Telemetry & Aggregation)
- 任务目标:实现多状态 Filter 与用户阅读数据的反馈回路。
- 关键技术栈:RxJS (bufferCount, bufferTime), Intersection Observer API。
- 核心模块:
- 批处理调度器:针对 Aggregation 阶段,使用 RxJS 的缓冲操作符,在达到数量或时间阈值时触发特定的 RPC 聚合调用。
- 阅读统计探针:基于页面的滚动事件与 Intersection Observer,计算用户的实际停留时间与可见内容量,生成打分日志。
- 反馈推流机制:周期性地将本地存储的遥测日志通过网络发送给后端模型训练/微调服务。