Skip to content

[P2][架构] OperationExecutor 反向依赖插件与 Application,执行内核缺少清晰的依赖边界 #156

Closed

Description

@LIghtJUNction

范围与基线

本项来自架构审查,只评价包依赖、类职责和装配关系,不是具体业务实现的缺陷报告,也不声称存在运行时循环导入或权限绕过。

基线:476e64f04ed1d9c7dcab4a41c4f3cdb72faad6a7(tree 40ca207a3c49be347120e058e47ed328ec4e3098)。作为 #85 的独立架构子项,依据权威设计第02、09、14章。

已观察到的结构

  • application.py 是装配入口,导入 OperationExecutor,并向各插件的 install(app) 传入应用对象。这部分装配职责本身合理。
  • core/executor.py 的 OperationExecutor 除已有的 registry、metadata、contents、认证/授权、clock、signer 依赖外,又持有 application 回指。
  • 同一内核模块直接导入 msg.plugins.batch.packets,并通过 self.application.settings.server.limits.max_request_bytes 获取配置。批处理结构规则因此跨在内核与具体插件之间。

结构可概括为:

Application ──装配──> OperationExecutor
     └──────装配──> plugins
OperationExecutor ──导入──> plugins.batch
OperationExecutor ──回指──> Application

架构问题

执行器应提供稳定的执行、认证、幂等及事务边界;插件应通过已登记契约使用它。当前依赖方向反过来了:基础执行内核需要认识具体插件的内部辅助函数,同时能沿整个应用对象访问未列入构造契约的服务。

这使插件的内部组织成为内核的依赖,也使执行器的实际依赖无法从构造接口完整看出。未来增加类似批处理的组合能力时,容易继续把插件特例写入内核,或把 Application 当作任意服务查找入口。这里的问题是职责归属和变更传播,并非某个函数长,也不等于已经出现功能错误。

建议的目标边界

保留模块化单体、单一 Registry 和单一 OperationExecutor,不增加通用工作流或任意 before/after hook。

先明确哪些批处理约束是执行框架自身的规则,哪些只是插件登记;框架规则由内核拥有,插件通过现有契约引用。执行器所需的配置或服务采用明确的窄参数、已有接口或可信固定策略,不传入整个 Application。不要求全仓搬目录或新增一套 Manager/Factory/ABC。

验收条件

  • 给出调整前后的模块依赖图及执行器依赖清单;core/executor.py 不再导入具体插件实现或回指整个装配对象。
  • 批处理结构约束只有一个明确所有者,不能通过复制 packets 形成第二份规则。
  • 执行器可用其声明的依赖独立装配测试;增加普通业务插件不需要修改内核的插件导入清单。
  • 有导入边界或装配契约检查,避免后续又从内核反向调用插件私有模块。
  • 保留 batch 原子性/独立执行差异、一次释放秘密的批处理限制、当前授权、幂等和唯一事务提交者;既有操作版本、短码、签署字节和回归不改变。

本项不替代 #85 的其他收敛任务,不要求部署,不关闭任何功能或安全总体验收 issue。

Activity

  1. LIghtJUNction commented on Sep 28, 2026

    @LIghtJUNction
    ContributorAuthor

    第二轮架构补充:修正执行器依赖时,一并明确通用协议契约的归属

    固定基线 476e64f04ed1d9c7dcab4a41c4f3cdb72faad6a7。本条作为原问题的依赖链补充,不另开一张同类 issue,也不扩大到完整协议重写。

    依赖链证据

    • plugins/batch.py 导入 transports.packet.REQUEST_SCHEMA/decode_packet。
    • transports/packet.py L1–32 声明通用 REQUEST_SCHEMA/RESULT_SCHEMA,又从 plugins.schemas 取得 obj/IDENTIFIER/STRING/BYTES/REF/SIGNATURE。
    • MCP/GraphQL/HTTP/客户端传输都使用该 packet 层;它的头部说明就是所有网络适配器共享的 wire decoding。
    core.executor → plugins.batch → transports.packet → plugins.schemas
                           业务包 ↔ 传输包(包级依赖)
    

    这里不声称 plugins.schemas 导入会运行所有插件,更不声称存在导入时死循环。新增证据反映的是:通用请求/结果契约、基础 schema 构造能力和具体传输安全规则的所有权横跨了不同层。

    对原修复方案的约束

    只把 batch.packets 搬到 core,再把上述依赖原样带进去,会把显式插件依赖换成更隐蔽的传输/插件依赖,不能算执行内核已经独立。

    请先区分:

    1. 所有入口共同使用的请求/结果数据契约、基础 schema 与中立编解码;
    2. 具体 HTTP/URL/压缩等传输表示和限制;
    3. batch 插件自己的业务登记与组合语义。

    共用契约应有一个职责中立、可独立引用的所有者;具体传输适配和业务插件分别消费它。URL 专用拒绝规则不要因为抽公共代码而误施加到非 URL 入口,也不能为了消除依赖复制 schema、绕过秘密交付约束或重新定义签署内容。

    建议原验收增加:检查新抽取模块的传递依赖,而不只搜索 core/executor.py 的直接 import;共同 packet/schema 仍只有一份来源,现有操作版本、字节编码、签名、短码和各协议限制保持兼容。这也与 #158 的最小客户端依赖边界协调处理。

  2. LIghtJUNction commented on Sep 28, 2026

    @LIghtJUNction
    ContributorAuthor

    本会话正在独立分支 fix/executor-core-20260929-2045 实施本 issue(包括第二轮共同 packet/schema 传递依赖补充)。失败回归头453d6f858e19136261278c7042c13598035aef1a,tree ae0b4f5e31dc1844c1abd0142da898b75b7779d4;专项36481310584已触发。core将只消费中立batch/event/wire契约和固定窄投影/事务通知接口;Application装配HTTP/SSH。#160已有另一分支推进,不重写其worker/contracts。本轮笔记docs/ISSUE_PROGRESS.md;测试未结束前不宣称修复通过。

  3. LIghtJUNction commented on Sep 29, 2026

    @LIghtJUNction
    ContributorAuthor

    架构验收完成,按已合入源码关闭

    交付PR #167;main 261c881,tree 6171f6041ffd0addaf72eadd35acf562f478281f。完整独立验收及4份产物散列见 #167 comment5887987237,不再停留在旧“待CI”状态。

    依赖图(也补齐第一项的记录要求)

    之前:Application → executor → plugins.batch → transports.packet → plugins.schemas
                            └──→ Application(任意服务回指)
    之后:Application ──窄参数/固定投影与通知接口──→ executor
          plugins.batch ──→ core.batching ──→ core.packet / core.schemas
          transports.packet ──同对象兼容导出──→ core.packet
          plugins.schemas ──同对象兼容导出──→ core.schemas
          executor ──→ core.batching / core.events / core.packet / execution_ports
    

    执行器依赖清单:registry、metadata、contents、authenticator、authorizer、clock、receipt_signer;请求大小、ResultProjection、TransactionalEventNotifications为显式窄参数。已有一次响应/恢复隔离接线由Application.new_executor统一装配,不再传入Application或允许按它查找任意服务。HTTP与SSH保留该共同工厂。

    • executor无插件导入/Application回指;独立新进程阻断plugins/transports/application仍能导入core协议链(不是只查直接import)。
    • batch packets、event_id、packet/schema均唯一中立所有者,旧路径按对象身份验证兼容;URL专用秘密拒绝/压缩不被搬到普通协议。
    • 不持有Application的独立执行器实际签名执行、投影、回放与缺投影整事务回滚通过;普通插件不要求新增内核插件import。
    • test_architecture_ports.py7项及test_execution_composition.py3项纳入完整CI,包含通知失败回滚和完整wire投影断言。
    • 现有batch独立/原子语义、秘密限制、当前授权、幂等、签名/receipt等回归仍执行。完整run36486040116:1,894/1,894去重node均通过,0失败/错误/跳过;另8conformance/构建/contracts gate通过。合并后main36546119029与恢复36546118849状态均success。

    只关闭此架构子项。#85其余工作和任何生产/功能总体验收不随之关闭;未部署或进行生产操作。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions