Bison 的模块化构想 #742
AzideCupric
started this conversation in
Ideas
Replies: 4 comments 5 replies
-
|
目前 next 分支的计划是这样的 |
Beta Was this translation helpful? Give feedback.
2 replies
-
def exec_loop(ctx):
posts = platform.get_new_posts(ctx)
for p in posts:
rendered = theme.render(p)
sender.send(rendered)其实总线的可靠性和可读性其实不如上面的伪代码简单 |
Beta Was this translation helpful? Give feedback.
2 replies
-
|
这里还需要明确一个问题,就是 site 的语义。 |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
还有一个问题是,platform 和 site 的爬取 API(类的定义)可能需要好好梳理一下 |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
就目前 Bison 的各功能实现来看,不少功能都存在较多的上下游调用依赖问题。比如 Bison 最主要的消息轮询业务,从 Schduler 开始,内部直接调用到 Platform、Site、Theme、MessageSend 四大功能,Bison 插件近乎所有的模块全都在这里耦合,导致整个结构缺乏灵活性和可扩展性,对单一功能的修改容易会波及到其余部分,也导致消息发送部分与蹲饼部分结合的过于紧密,以及渲染部分可能因为耗时过长而将调度循环阻塞。
实现目标
旨在从“ monolithic ”的调度器向“基于事件总线(Courier)”的松散耦合架构演变,大致包括:
成为一个更符合组织名的插件模块拆分说明
Scheduler(调度器)
仅负责按计划触发各个 Platform 的数据获取,不关心具体的数据处理和消息发送,如果本次调度获取到原始报文(RawPost),则通过 Courier 发送,然后立即继续调度下一个任务。
Platform(平台适配器)
Site(站点)
是对 Platform 的分类,调度器按 Site 为单位划分轮询循环执行轮询任务,同一个 Site 下的 Platforms 在同一循环中执行。
Theme(主题渲染器)
接收标准化 Post,根据运行实际、用户配置、Platform 默认配置将 Post 渲染为具体消息格式以备发送,支持多种可配置的消息模板和样式
Sender(发送器)
将渲染好的消息放入消息队列,负责将最终消息发送到目标平台(QQ/TG 等)
数据流图
按照上一节所述内容,大致可以由以下图示进行描绘:
sequenceDiagram participant S as Scheduler participant C as Courier participant W as Platform/Weibo participant T as Theme participant Sd as Sender Note over S, Sd: 阶段1: 调度和数据获取 S->>C: Parcel:<br/>- payload: {content: xxx}<br/>- metadata: {platform: weibo}<br/>- dest: fetcher<br/>- channel: main C->>W: 路由(fetcher, main) W->>W: 调用微博API(fetch-api) W->>W: 生成RawPost列表 loop 每个RawPost W->>C: Parcel:<br/>- payload: RawPost<br/>- metadata: {platform: weibo}<br/>- dest: normalizer<br/>- channel: main end Note over S, Sd: 阶段2: 数据解析 C->>W: 路由(normalizer, main) W->>W: 解析为Post(parse-api) W->>C: Parcel:<br/>- payload: Post<br/>- metadata: {platform: weibo}<br/>- dest: renderer<br/>- channel: render Note over S, Sd: 阶段3: 消息渲染 C->>T: 路由(renderer, render) T->>T: 选择Theme T->>T: 渲染为Message T->>C: Parcel:<br/>- payload: Message<br/>- metadata: {target: xxx}<br/>- dest: sender<br/>- channel: message Note over S, Sd: 阶段4: 消息发送 C->>Sd: 路由(sender, message) Sd->>Sd: 进入发送队列构建可发送消息 Sd->>Sd: 发送到QQ群/TG等信使(Courier)机制
在上文的模块拆分中可以发现,有些数据会被一个模块产出,接着被一个模块接收,对于这一个统一的行为,可以封装出一个模块来处理,考虑到本项目的由来和名称,可以将该模块称之为信使(Courier
,这下终于物流了),这个模块提供一个统一入口,模块投递被包装为包裹(Parcel)的数据,Courier 将其派送到对应的处理点。这些处理点在各自的模块进行注册和实现,通过声明处理点的地址(Tag)、特定信道(Channel),处理点接收可以处理的包裹,并对包裹合法性进行验证,根据需要消费或者加工后转派,实现模块间数据流的链接。信使模块也可以认为是一种总线(Bus)模块间的数据流转在这里进行。模块间的数据流转由 Courier 统一负责,这样各个模块只消保证 Parcel 出入口能够与其他模块对接,数据流就可以保持联通,内部的实现可以有更大程度的自主性。这使得各个模块的子插件化成为可能,Bison可以通过子插件加载,甚至直接在
pyproject.toml中按需加载子插件,就能注册不同的处理点,实现可按需组合的数据流。当然这是比较高级的玩法了(信使的派送机制也为插件的扩展/定制化提供可能,下游用户只需要自行注册替换一个默认处理点,就可以实现原有数据流的变更,提升了定制化空间。另外只要构建出符合接收条件的 Parcel,数据就能被处理,这样我们就拥有了几乎在程序的各个位置发送通知消息的能力 —— 构造一个消息包裹交给信使派送即可。
核心概念
Courier(信使):模块间通信的总线系统,负责路由和派送数据包。
Parcel(包裹):数据的标准包装格式,包含:
data: 实际被处理的数据(RawPost、Post、Message 等)metadata: 控制待处理数据行为的数据,这些数据不是被直接处理的数据dest: 目标地址(Tag)。channel: 信道类型(Channel),声明 Parcel 通过哪个信道发送。Tag(地址):处理点的标识符,如
fetcher、parser、sender等。声明 Parcel 需要发送到哪里。Channel(信道):数据类型或处理阶段的标识,如
main、message、render等。对于一些繁忙的地址,可以为其创建一个单独的 Channel 来传输包裹,减少等待处理 Parcel 的时间。工作机制
Platform/Theme 的按需加载(子插件化)
之所以提出这两大功能的子插件化,是因为在开发过程中适配不用的 Platform、Theme 时,总是会引入只有这个极小部分才需要的依赖,而用户在实际使用时,有些 Platform 和 Theme 完全不会被使用,这些依赖就变成了累赘,也使得项目的依赖项数显得过于的多~~(不好看!)~~。
在设计之初 Theme 就天然支持外部注册,其实现参考于 Platform,因此 Platform 自然不难。
因此考虑将目前项目中 builtin 的 Platform、Theme 迁移到 extra_plugins 目录中,使用 uv 的 monorepo 结构进行管理,使用子插件的形式,启动时将子插件中的 Platform 注册到本体的平台管理器中。
Bison Core 与非核心模块
将原有代码文件结构重新进行整理,提出 Core 的概念。Core 是 Bison 业务实现的最小组成,不包含特定的通信协议或者框架依赖,Schduler、 Platform(Abstract)、Site、Theme(Abstract)、Courier 的模块在这里实现。
而诸如订阅处理、Cookie处理、Web API以及具体的消息发送处理,则是非核心,依赖某些特定框架协议的模块,不进入Core部分。
Core 模块(框架无关)
核心职责:
包含组件:
Courier: 消息总线系统Parcel/Tag/Channel基础数据类型Scheduler: 任务调度器Platform/Site/Theme抽象基类非核心模块(框架特定)
适配层组件:
设计原则:
未来展望
(做不完了)BISON__PLATFORM__XXX环境变量,或者支持一个配置文件集中配置Beta Was this translation helpful? Give feedback.
All reactions