refactor(startup): isolate chain composition

This commit is contained in:
jxxghp
2026-08-29 18:04:18 +08:00
parent 808f2439ef
commit b658f7c2c0
12 changed files with 393 additions and 148 deletions

View File

@@ -62,7 +62,7 @@ MoviePilot V3 已经形成较清晰的模块化单体:`foundation`、`domain`
| `chain` | 多入口复用的用例编排与 Module 动态分发已稳定,包根 SCC 已清零 | God object、私有长方法、无参构造和资源物化过重 |
| `db/oper` | Model/Oper 已不自建 Session、不自行提交 | 无 Session Facade 仍被宿主组合根注入,业务操作可能拆成多个事务 |
| `db/adapters` | 已有显式 Session/UoW 的参考切片 | Port 返回类型不够稳定;Outbox 的 stage 与自提交 dispatcher store 混在一个类型 |
| `startup` | 已是 HostRuntime 和生命周期组合根 | `initializers/modules.py` 高扇出,仍有导入期 provider 注册和具体对象目录装配 |
| `startup` | 已是 HostRuntime 和生命周期组合根;Chain 兼容上下文由 `composition/chain.py` 独立装配 | `initializers/modules.py` 仍有其他领域高扇出和具体对象目录装配 |
| API/Command/Scheduler | 多数入口已转向 Chain/Application;Scheduler 单体已拆为同名职责包并由 startup 注入业务 callable | Agent/System/Plugin 等入口仍承担较多业务与 I/O 编排 |
| `sdk`/`compat` | 精确映射、稳定插件 ABI 和宿主 canonical 路径已落地 | SDK 仍暴露部分可变全局对象/具体 Manager,只能渐进收窄,不能直接删除 |
@@ -70,7 +70,7 @@ MoviePilot V3 已经形成较清晰的模块化单体:`foundation`、`domain`
| 指标 | 当前值 | 解释 |
|---|---:|---|
| 宿主 Python 模块 / 内部依赖边 | 970 / 8,279 | `dependency-baseline.json` 当前快照 |
| 宿主 Python 模块 / 内部依赖边 | 971 / 8,306 | `dependency-baseline.json` 当前快照 |
| 非平凡 SCC | 1 | 仅保留精确 containment 的 29 模块 TMDB 移植包环 |
| 跨层 DB 边界债务 | 0 | Application、Chain、API、Agent、Runtime、Workflow 到 DB 的受控债务均为零 |
| Model/Oper 事务债务 | 0 | 自建 Session、自动事务装饰器、直接 commit/rollback 等基线均为零 |
@@ -78,7 +78,7 @@ MoviePilot V3 已经形成较清晰的模块化单体:`foundation`、`domain`
| Event Contract | 53 | 均已有 payload model,但当前全部是 diagnostic enforcement |
| Python 源码量 | 约 298,700 行 | 60 个文件超过 1,000 行,10 个超过 2,000 行 |
| 长方法 | 299 个超过 80 行 | 70 个超过 150 行,23 个超过 250 行;大量是私有方法 |
| 全量 mypy 历史债务 | 10,335 / 593 文件 | strict frontier 当前覆盖 41 个文件,Domain projection 与既有 owner 拆分的受益调用方低水位已固化 |
| 全量 mypy 历史债务 | 10,335 / 593 文件 | 新 Chain composition owner 零类型债,`modules.py` 低水位下降 1;strict frontier 当前覆盖 41 个文件 |
| Ruff 历史诊断 | 648 | 低水位门禁通过,但规则集只覆盖 `E4/E7/E9/F/I` |
| 覆盖率低水位 | Application 81.00%,Domain 80.67% | Chain、Runtime、Agent、Adapter、Startup 未进入包级覆盖率门禁 |
@@ -672,10 +672,11 @@ Pylint 10/10、Ruff、mypy/复杂度 ratchet、宿主与最新官方插件基线
插件持久化迁入既有 `startup/composition/{configuration,database}.py`;initializer 只调用组合 API。
数据库 runtime 拒绝重入,Worker 成功后才发布事务入口;成功关闭与启动失败会对称撤销本批 provider、
释放数据库引擎,并在模块 owner 收敛后清除 `app.state.host_runtime`。
- [x] L4.2 已将 network、security 与 agent 装配迁入单词 owner;Agent composition 在 Worker 启动后
读取容量,并让 `HostRuntime`、兼容 provider、工具管理器与 Scheduler 共享同一数据和任务对象。
- [ ] 继续将 Chain、server、outbox 与 HostRuntime 构造按领域移到
`startup/composition/*`,最终让 initializer 只负责顺序、注册和是否重启的决策。
- [x] L4.2 已将 network、security、agent、server、outbox 与 Chain 装配迁入单词型
`startup/composition/*` owner;Agent composition 在 Worker 启动后读取容量并共享同一数据和任务对象,
Chain 通过 provider 保持插件无参构造兼容,旧 Transfer command 只在真实调用时延迟导入。
- [ ] 继续将 HostRuntime 剩余构造移到 `startup/composition/runtime.py`,最终让 initializer
只负责顺序、注册和是否重启的决策。
- [ ] 保留生命周期 manifest 和顺序快照;高扇出在组合根是允许的,但业务实现不能继续沉积其中。
### ARCH-204 收敛 sync/async 重复与测试存量

View File

@@ -285,7 +285,9 @@ sequenceDiagram
`HostRuntime.settings` 的窄服务读写可变部署设置,业务域不接触 Settings 实例;生产与测试组合根统一
复用 `startup/composition/configuration.py` 的映射、快照加载与发布。`startup/composition/database.py`
持有数据库 worker、兼容事务 runner、查询/插件持久化和旧 `ApiDataPorts` 的具体装配;initializer
只保留顺序调用。`startup/composition/security.py` 统一装配认证、用户查询、PassKey 与 Web 访问
只保留顺序调用。`startup/composition/chain.py` 集中构造无参 Chain 兼容上下文及其持久化、事件、
Outbox、消息和模块分发依赖,并延迟绑定旧 Transfer command 与壁纸 Chain,避免组合根导入环。
`startup/composition/security.py` 统一装配认证、用户查询、PassKey 与 Web 访问
provider,并将同一 `AuthenticationRuntime` 交给 HostRuntime;`startup/composition/network.py` 统一
装配网络应用端口;`startup/composition/agent.py` 构造并发布唯一的 Agent 数据、会话和自主任务对象,
`HostRuntime`、工具管理器与 Scheduler 复用同一对象身份。`ApiDataPorts` 仅保留旧导入 ABI,
@@ -747,8 +749,8 @@ flowchart LR
| 指标 | 当前值 |
|---|---:|
| Python 模块 | 970 |
| 内部导入边 | 8,279 |
| Python 模块 | 971 |
| 内部导入边 | 8,306 |
| 非平凡 SCC | 1(精确 containment 的 TMDB 移植包环) |
| Application / Chain 具体 Adapter 直连 | 0 / 0 |
| Direct egress | 53(债务已清零,53 条精确 containment) |

View File

@@ -141,6 +141,10 @@ runtime/settings construction and publication. `startup/composition/database.py`
owns the process database worker, compatibility transaction runner, query services,
plugin persistence and legacy API data-port wiring. Initializers call these owners in
startup order and must not recreate their concrete construction.
`startup/composition/chain.py` owns the no-argument Chain compatibility context,
typed persistence/dispatch object graph, lazy legacy Transfer command binding and
wallpaper-provider publication. `initializers/modules.py` only passes the already
constructed repositories in startup order and must not recreate those dependencies.
`startup/composition/security.py` owns authentication, user lookup, PassKey and Web
access provider assembly; `initializers/modules.py` only invokes that owner and places
its returned `AuthenticationRuntime` into the host runtime.
@@ -151,7 +155,7 @@ startup order and must not recreate their concrete construction.
`startup/composition/outbox.py`
owns durable handler validation, lazy event/notification replay binding and the
short-transaction dispatcher factory. Initializers call this owner in
startup order and must not recreate their concrete construction. Database runtime
startup order and must not recreate its concrete construction.
`startup/composition/server.py` owns MoviePilot Server report/share service
construction and registration, including lazy local-data readers and external
transport callbacks; `initializers/modules.py` retains only its startup-order call
@@ -160,8 +164,8 @@ and the later explicit network warmup. Database runtime
chat persistence and autonomous-task repository/execution service set. It may accept
the Agent initializer's data-context registrar as a callback, but must not import
`startup.initializers`; tool-manager, scheduler and Agent activation order remains in
the initializer. Database runtime
ownership rejects overlapping lifespans; after a successful worker shutdown, the
the initializer. Database runtime ownership rejects overlapping lifespans; after a
successful worker shutdown, the
configuration/database composition owners must revoke every provider they published
before releasing database connections. Other domain providers remain owned by their
matching composition batch and must satisfy the same symmetric lifecycle contract