mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-06 16:16:44 +08:00
- 修复 RequestStartupBenchmarks 的 baseline 分组、初始化阶段对齐与 MediatR 重复注册问题 - 新增共享 dispatcher cache helper,并统一 benchmark 宿主的 MediatR logging/license 过滤配置 - 更新 cqrs-rewrite 跟踪与 trace,记录 PR #326 锚点、验证去重和 startup benchmark 的残留运行风险
31 KiB
31 KiB
CQRS 重写迁移追踪
2026-04-30
阶段:历史 PR #307 active 入口收敛(CQRS-REWRITE-RP-076)
- 继续沿用
$gframework-pr-review对PR #307做 latest-head triage,本轮只处理仍成立的ai-plan恢复入口问题 - 主线程确认当前远端权威信号:
- 当时分支对应
PR #307,状态为OPEN - 远端
CTRF最新汇总为2247/2247passed MegaLinter仅剩dotnet-format的Restore operation failed环境噪音- 仍未闭环的 review 重点集中在
cqrs-rewriteactive tracking / trace 仍保留过多历史锚点,而非新的运行时代码缺陷
- 当时分支对应
- 本轮决策:
- 将 active tracking 收敛为单一恢复入口,只保留
RP-076、PR #307、活跃风险、最近权威验证与下一推荐步骤 - 将 active trace 收敛为当前阶段的关键事实与决策,不再在默认恢复入口中保留
RP-062之后的长阶段流水账 - 新增
archive/traces/cqrs-rewrite-history-rp062-through-rp076.md承接RP-062至RP-076的详细 trace 历史,保持旧阶段仍可追溯
- 将 active tracking 收敛为单一恢复入口,只保留
验证(RP-076)
python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json --json-output <temporary-json-output>- 结果:通过
- 备注:确认
PR #307的当前 review 重点已收敛到ai-plan文档收尾
dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release- 结果:通过,
0 warning / 0 error
- 结果:通过,
dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Stream_Invoker_Provider_Metadata_When_Runtime_Lacks_Stream_Provider_Interface|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Stream_Invoker_Provider_Metadata_When_Runtime_Lacks_Stream_Descriptor_Enumerator|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Stream_Invoker_Provider_Metadata_When_Runtime_Lacks_Stream_Descriptor_Type|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Stream_Invoker_Provider_Metadata_When_Runtime_Lacks_Stream_Descriptor_Entry_Type|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Stream_Invoker_Provider_Metadata_When_Runtime_Contract_Is_Available"- 结果:通过,
5/5passed
- 结果:通过,
当前下一步(RP-076)
- 当时继续按
PR #307的 latest-head review 收尾,优先保持 active tracking 与 active trace 的单一锚点一致 - 若继续推进代码切片,先复核 request 侧是否仍存在与 stream invoker gate 对称的生成合同遗漏
- 进入下一批前继续使用最小 Release build 或 targeted test 作为权威验证,避免把环境噪音误判为代码问题
2026-05-04
阶段:request invoker provider gate 对称回归(CQRS-REWRITE-RP-077)
- 使用
$gframework-batch-boot 25继续feat/cqrs-optimization的 CQRS 收口批次 - 批次目标:在 branch diff 相对
origin/main接近25个文件前,补齐低风险的 generator 合同回归切片 - 本轮先确认当前 worktree 已无
local-plan遗留恢复入口,随后转入cqrs-rewrite的 request / stream invoker provider gate 对称性复核 - 结论:
- 生产代码已经同时检查 request provider、enumerator、descriptor 与 descriptor entry 四项 runtime 合同
- request 侧测试只覆盖缺少 provider / enumerator,缺少 descriptor / descriptor entry 的回归覆盖落后于 stream 侧
- 已补齐:
Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_TypeDoes_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_Entry_Type- source emission XML 文档同步说明 provider gate 依赖完整 descriptor / descriptor entry 合同
验证(RP-077)
dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_Type|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_Entry_Type|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Provider_Interface|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_Enumerator"- 结果:通过,
4/4passed
- 结果:通过,
dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release- 结果:通过,
0 warning / 0 error
- 结果:通过,
python3 scripts/license-header.py --check- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定
GIT_DIR/GIT_WORK_TREE后运行,避免脚本内部 plaingit ls-files误判仓库上下文
git diff --check- 结果:通过
当前下一步(RP-077)
- 继续使用
origin/main作为$gframework-batch-boot 25的基线,复算 branch diff 后决定是否还能接下一批 - 若继续推进代码切片,优先查找 request / stream invoker provider runtime 合同之外的同类对称测试缺口
阶段:mixed fallback attribute usage 回归(CQRS-REWRITE-RP-078)
- 继续沿用
$gframework-batch-boot 25,当前 branch diff 仍低于阈值 - 复核 fallback metadata runtime contract 后确认:
- mixed fallback 在 runtime 允许多个 fallback attribute 实例时已有直接
Type+ 字符串拆分回归 - runtime 同时支持
params Type[]/params string[]但不允许多个 fallback attribute 实例时,缺少锁定“整体回退到单个字符串 attribute”的回归
- mixed fallback 在 runtime 允许多个 fallback attribute 实例时已有直接
- 已补齐:
Emits_String_Fallback_Metadata_For_Mixed_Fallback_When_Runtime_Disallows_Multiple_Fallback_AttributesReplaceAttributeUsageForType测试辅助方法,用于构造 runtime attribute usage 变体而不复制大型 source fixture
验证(RP-078)
dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_String_Fallback_Metadata_For_Mixed_Fallback_When_Runtime_Disallows_Multiple_Fallback_Attributes"- 结果:通过,
1/1passed
- 结果:通过,
python3 scripts/license-header.py --check- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定
GIT_DIR/GIT_WORK_TREE后运行
git diff --check- 结果:通过
当前下一步(RP-078)
- 继续复算 branch diff vs
origin/main,若仍低于25个文件可继续下一批 - 下一批优先查看 fallback metadata 与 generated invoker provider 之外是否还有同类 runtime contract gate 回归缺口
阶段:基础 generated registry contract gate 回归(CQRS-REWRITE-RP-079)
- 继续沿用
$gframework-batch-boot 25,当前 branch diff 仍低于阈值 - 复核 generator 基础启用条件后确认:缺少
ICqrsHandlerRegistry时,runtime 不具备承载 generated registry 的基础接口合同,应整体跳过发射 - 已补齐:
Does_Not_Generate_Registry_When_Runtime_Lacks_Handler_Registry_Interface
验证(RP-079)
dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Generate_Registry_When_Runtime_Lacks_Handler_Registry_Interface"- 结果:通过,
1/1passed
- 结果:通过,
python3 scripts/license-header.py --check- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定
GIT_DIR/GIT_WORK_TREE后运行
git diff --check- 结果:通过
当前下一步(RP-079)
- 继续复算 branch diff vs
origin/main,若仍低于25个文件可继续下一批 - 下一批优先复核基础 generation gate 中其他必需 runtime contracts 是否也需要同类回归覆盖
阶段:基础 generated registry contract gate 扩展回归(CQRS-REWRITE-RP-080)
- 将
RP-079的单一 handler registry interface 缺失回归扩展为基础 generation gate 参数化测试 - 已补齐缺失分支:
ICqrsHandlerRegistryINotificationHandler<TNotification>IStreamRequestHandler<TRequest, TResponse>CqrsHandlerRegistryAttribute
- stream handler interface 变体采用类型重命名构造 runtime metadata miss,避免删除命名空间尾部单行接口时引入输入编译错误
验证(RP-080)
dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Generate_Registry_When_Runtime_Lacks_Required_Generation_Contract"- 结果:通过,
4/4passed
- 结果:通过,
python3 scripts/license-header.py --check- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定
GIT_DIR/GIT_WORK_TREE后运行
git diff --check- 结果:通过
当前下一步(RP-080)
- 继续复算 branch diff vs
origin/main,若仍低于25个文件可继续下一批 - 下一批优先复核基础 generation gate 中 logging / DI 依赖是否已有合适的输入编译安全回归覆盖方式
阶段:基础 generated registry external contract gate 回归(CQRS-REWRITE-RP-081)
- 延续
RP-080的参数化基础 generation gate 测试,将外部 logging / DI 依赖也纳入同一组静默跳过回归 - 已补齐缺失分支:
GFramework.Core.Abstractions.Logging.ILoggerMicrosoft.Extensions.DependencyInjection.IServiceCollection
- 两个变体均通过类型重命名构造 runtime metadata miss,保持输入源码可编译,避免把依赖缺失测试误写成编译失败测试
验证(RP-081)
dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Generate_Registry_When_Runtime_Lacks_Required_Generation_Contract"- 结果:通过,
6/6passed
- 结果:通过,
python3 scripts/license-header.py --check- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定
GIT_DIR/GIT_WORK_TREE后运行
git diff --check- 结果:通过
当前下一步(RP-081)
- 继续复算 branch diff vs
origin/main,若仍低于25个文件可继续下一批 - 下一批优先复核基础 generation gate 中 request handler contract 与 handler registry attribute 以外是否还有可安全构造的缺失分支
阶段:基础 generated registry request handler gate 回归(CQRS-REWRITE-RP-082)
- 延续
RP-081的基础 generation gate 参数化测试,补齐IRequestHandler<TRequest,TResponse>缺失分支 - 该变体同样通过类型重命名构造 runtime metadata miss,保持输入源码可编译
- 至此基础 generation gate 中可安全构造的缺失分支已覆盖:
- request handler interface
- notification handler interface
- stream handler interface
- handler registry interface
- handler registry attribute
- logging interface
- DI service collection interface
验证(RP-082)
dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Generate_Registry_When_Runtime_Lacks_Required_Generation_Contract"- 结果:通过,
7/7passed
- 结果:通过,
python3 scripts/license-header.py --check- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定
GIT_DIR/GIT_WORK_TREE后运行
git diff --check- 结果:通过
当前下一步(RP-082)
- 继续复算 branch diff vs
origin/main,若仍低于25个文件可继续下一批 - 下一批优先复核基础 generation gate 之外的 runtime contract 或 fallback selection 分支;基础 gate 的可安全构造缺失分支已覆盖
阶段:PR #323 review 锚点收敛(CQRS-REWRITE-RP-082)
- 使用
$gframework-pr-review重新拉取当前分支 PR review payload,确认当前分支对应PR #323,状态为OPEN - 本轮 latest-head open AI thread 仅指出 active tracking 中仍保留
PR #307作为当前 PR 锚点;本地复核后确认该反馈仍成立 - 已将 active tracking 的当前 PR 锚点、活跃事实、最近 PR review 备注和下一推荐步骤统一到
PR #323 PR #307仅保留为历史 PR 说明和较早 trace 段落,不再作为 active 恢复入口
验证(PR #323 review)
python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json --json-output <temporary-json-output>- 结果:通过
- 备注:确认
PR #323只有 1 个 CodeRabbit open thread,指向 active tracking 的 PR 锚点漂移
- 远端
CTRF最新汇总为2274/2274passed MegaLinter当前仅报告dotnet-format的Restore operation failed环境噪音,未提供本地仍成立的文件级格式诊断git diff --check- 结果:通过
python3 scripts/license-header.py --check- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定
GIT_DIR/GIT_WORK_TREE后运行
dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release- 结果:通过,
0 warning / 0 error
- 结果:通过,
当前下一步(PR #323 review)
- 若 review 重新触发后仍有 latest-head open thread,继续以
PR #323为当前唯一 PR 恢复锚点复核 - 后续若继续推进代码切片,优先复核基础 generation gate 之外的 runtime contract 或 fallback selection 分支
2026-05-06
阶段:mixed invoker provider 排序回归(CQRS-REWRITE-RP-083)
- 使用
$gframework-batch-boot 50继续feat/cqrs-optimization的 CQRS 收口批次 - 批次目标:在 branch diff 相对
origin/main接近50个文件前,继续补齐低风险的 generator runtime contract / emission 回归 - 本轮基线选择:
origin/main a8c6c11e,committer date2026-05-05 13:14:24 +0800main a8c6c11e,committer date2026-05-05 13:14:24 +0800- 当前分支
feat/cqrs-optimization a8c6c11e,committer date2026-05-05 13:14:24 +0800
- 启动时 branch diff vs
origin/main为0files /0lines,因此继续选择低风险测试回归切片 - 本轮复核
CreateGeneratedRegistrySourceShape与 invoker emission 路径后确认:- 现有测试已覆盖 request / stream provider 的单一 direct 场景、单一 reflected-implementation 场景、precise reflected 跳过边界,以及各项 runtime contract 缺失分支
- 尚未锁定“同一 registry 同时包含 direct registration 与 reflected-implementation registration”时的 descriptor 顺序与
Invoke*HandlerN编号稳定性
- 已补齐:
Emits_Request_Invoker_Provider_Metadata_In_Stable_Order_For_Mixed_Direct_And_Reflected_ImplementationsEmits_Stream_Invoker_Provider_Metadata_In_Stable_Order_For_Mixed_Direct_And_Reflected_Implementations- 两组 source fixture:
MixedRequestInvokerProviderSource、MixedStreamInvokerProviderSource
- 通过新增回归,显式锁定以下约束:
- provider descriptor 条目按稳定实现排序输出
InvokeRequestHandler0/1与InvokeStreamHandler0/1的方法编号随 emission 顺序连续增长- 隐藏实现类型不会破坏 direct registration 与 reflected-implementation registration 的混合发射
验证(RP-083)
dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Request_Invoker_Provider_Metadata_In_Stable_Order_For_Mixed_Direct_And_Reflected_Implementations|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Stream_Invoker_Provider_Metadata_In_Stable_Order_For_Mixed_Direct_And_Reflected_Implementations"- 结果:通过,
2/2passed
- 结果:通过,
当前 stop-condition 度量(RP-083)
- primary metric:branch diff files vs
origin/main - 当前说明:active batch 尚未提交时,基于
HEAD的 branch diff 仍显示0files /0lines;提交本批后再以新HEAD复算累计 branch diff
当前下一步(RP-083)
- 提交本轮 mixed invoker provider 排序回归后,复算 branch diff vs
origin/main,确认50文件阈值仍有充足余量 - 若继续推进代码切片,优先复核 invoker provider 之外的 runtime contract 或 fallback selection 分支
阶段:benchmark 基础设施引入(CQRS-REWRITE-RP-084)
- 用户明确将当前长期分支目标上提为:系统性吸收
ai-libs/Mediator的实现思路与设计哲学,并将可取部分纳入GFramework.Cqrs - 本轮据此调整批次目标,不再把关注点收缩到单个 generator 回归,而是建立能持续比较和吸收设计差异的 benchmark 基础设施
- 参考
ai-libs/Mediator的 benchmark 设计后,本轮采纳的核心结构包括:- 独立 benchmark 项目壳,而非扩展现有 NUnit 测试项目
- 共享
Fixture输出并校验场景配置 Request/Notification两个 messaging 场景作为首批最小落点- 自定义列
CustomColumn,为后续矩阵扩展保留可读结果标签
- 本轮新增:
GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csprojGFramework.Cqrs.Benchmarks/Program.csGFramework.Cqrs.Benchmarks/CustomColumn.csGFramework.Cqrs.Benchmarks/Messaging/Fixture.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkContext.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.csGFramework.Cqrs.Benchmarks/README.md
- 设计取舍:
- 使用最小
ICqrsContextmarker,避免把完整ArchitectureContext初始化成本混入 steady-state dispatch - 直接复用
GFramework.Cqrs.CqrsRuntimeFactory与MicrosoftDiContainer,让基准聚焦于 runtime dispatch / publish - 外部对照组先接入
MediatR,保持与Mediatorbenchmark 的对照哲学一致;但本轮仍只做最小 request / notification 场景 - 暂不把 source generator benchmark、cold-start 独立工程或完整 pipeline / stream 矩阵一起引入,避免首批 scope 失控
- 使用最小
- 兼容性修正:
- 在根
GFramework.csproj中显式排除GFramework.Cqrs.Benchmarks/**,避免 meta-package 意外编译 benchmark 源码 - 将 benchmark 项目加入
GFramework.sln,保持仓库级工作流完整
- 在根
验证(RP-084)
dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release- 结果:通过,
0 warning / 0 error
- 结果:通过,
GIT_DIR=<worktree-git-dir> GIT_WORK_TREE=<worktree-root> python3 scripts/license-header.py --check- 结果:通过
git diff --check- 结果:通过
当前 stop-condition 度量(RP-084)
- primary metric:branch diff files vs
origin/main - 当前说明:本轮仍在
50文件阈值以内,可继续按 benchmark 场景或 CQRS runtime 对照能力分批推进
当前下一步(RP-084)
- 继续扩展
GFramework.Cqrs.Benchmarks,优先补齐 pipeline、stream、cold-start 与 generated invoker provider 对照场景 - 当后续有具体 runtime 优化切片时,用该 benchmark 项目验证是否真正吸收到了
Mediator的低开销 dispatch 设计收益
阶段:stream request benchmark 对照(CQRS-REWRITE-RP-085)
- 继续沿用
$gframework-batch-boot 50,当前 branch diff 相对origin/main仍明显低于阈值 - 在
RP-084已建立独立 benchmark 项目后,本轮优先补齐ai-libs/Mediator/benchmarks/Mediator.Benchmarks/Messaging/StreamingBenchmarks.cs对应的最小 stream 场景 - 选择 stream 作为第二批 benchmark 的原因:
- 已有独立的
CreateStreamruntime 路径和单独的 stream invoker provider 元数据契约 - 与
Mediator的 messaging benchmark 分层直接对应 - 不需要像 pipeline / cold-start 那样先进一步澄清运行时或宿主边界
- 已有独立的
- 本轮新增:
GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/README.md中的 stream 场景说明
- 设计约束:
- 保持与前一批一致的三路对照:
Baseline、GFramework.Cqrs、MediatR - 基准测量“完整枚举 3 个元素”的全量消费成本,而不是只测创建异步枚举器
- 使用最小
ICqrsContextmarker,继续避免把完整ArchitectureContext初始化成本混入 steady-state stream dispatch
- 保持与前一批一致的三路对照:
- 结论:
- 当前 benchmark 项目已经覆盖
Request、Notification、StreamRequest三个核心 messaging steady-state 场景 - 下一批更适合转向 request pipeline 数量矩阵或 cold-start / initialization,而不是继续扩同层次的 messaging 基线
- 当前 benchmark 项目已经覆盖
验证(RP-085)
dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release- 结果:通过,
0 warning / 0 error
- 结果:通过,
GIT_DIR=<worktree-git-dir> GIT_WORK_TREE=<worktree-root> python3 scripts/license-header.py --check- 结果:通过
git diff --check- 结果:通过
当前 stop-condition 度量(RP-085)
- primary metric:branch diff files vs
origin/main - 当前说明:新增 stream benchmark 后仍处于
50文件阈值以内,适合继续下一批 request pipeline 或 cold-start 场景
当前下一步(RP-085)
- 继续扩展
GFramework.Cqrs.Benchmarks,优先补齐 request pipeline 数量矩阵,随后再评估 cold-start / initialization - 当需要验证 generated invoker provider 的实际收益时,把 request benchmark 扩展为 reflection / generated provider 对照,而不是只停留在框架间对比
阶段:request pipeline 数量矩阵(CQRS-REWRITE-RP-086)
- 继续沿用
$gframework-batch-boot 50,当前 branch diff 相对origin/main仍明显低于阈值 - 本轮把 benchmark 关注点从单纯 messaging steady-state 扩展到 request pipeline 编排行为,原因是:
ai-libs/Mediator的对照价值已经不只在 request / notification / stream 三个入口本身,还在 pipeline 包装策略与生命周期取舍GFramework.Cqrs.Internal.CqrsDispatcher已按behaviorCount缓存RequestPipelineExecutor<TResponse>形状,因此单独量化0 / 1 / 4个行为的 steady-state 开销有直接信息密度
- 本轮新增:
GFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/README.md中的 request pipeline 场景说明
- 设计取舍:
- 采用
0 / 1 / 4个 pipeline 行为,而不是立即扩到更大的参数空间,先锁定最有代表性的无行为 / 少量行为 / 常见多行为矩阵 - 使用最小 no-op 行为族,不引入日志、计时或上下文刷新逻辑,避免把测量结果污染成业务行为成本
GFramework.Cqrs与MediatR侧都只注册当前 benchmark 请求对应的闭合行为类型,确保矩阵反映编排成本而非程序集扫描差异
- 采用
- 接受的只读 subagent 结论:
- 下一批 benchmark 继续优先考虑
cold-start / initialization与generated provider对照,而不是立即照搬Mediator的 large-project 维度 - 当前
GFramework.Cqrs.Benchmarks仍未接入Mediator包和GFramework.Cqrs.SourceGenerators,因此本轮不扩成Mediator_IMediator/ generated-provider 对照,避免 scope 失控
- 下一批 benchmark 继续优先考虑
- 结论:
- 当前 benchmark 项目已经覆盖
Request、Notification、StreamRequest与RequestPipeline - 后续若要继续贴近
Mediator的 comparison benchmark,最值得优先补的是 initialization / first-hit 与 generated invoker provider,而不是继续横向堆更多 steady-state messaging 入口
- 当前 benchmark 项目已经覆盖
验证(RP-086)
dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release- 结果:通过,
0 warning / 0 error
- 结果:通过,
当前 stop-condition 度量(RP-086)
- primary metric:branch diff files vs
origin/main - 当前说明:提交前基于
HEAD的 branch diff 仍为14files,距离50文件阈值仍有明显余量
当前下一步(RP-086)
- 提交本轮 request pipeline benchmark 后,继续扩展
GFramework.Cqrs.Benchmarks,优先补齐 initialization / cold-start 场景 - 当需要验证 dispatcher 预热与 source generator 收益时,引入 generated invoker provider 对照,并评估是否同时接入
Mediatorconcrete runtime 作为更贴近设计哲学的外部参照
阶段:request startup 基线(CQRS-REWRITE-RP-087)
- 继续沿用
$gframework-batch-boot 50,当前 branch diff 相对origin/main仍明显低于阈值 - 本轮目标:把 benchmark 从 steady-state dispatch 再向前推进一层,补齐与
ai-libs/Mediator/benchmarks/Mediator.Benchmarks/Messaging/Comparison/*更接近的 startup 维度 - 本轮新增:
GFramework.Cqrs.Benchmarks/Messaging/RequestStartupBenchmarks.csGFramework.Cqrs.Benchmarks/README.md中的 startup 场景说明
- 设计取舍:
Initialization只测“从已配置宿主解析/创建 runtime 句柄”的成本,不把完整架构初始化混入 benchmarkColdStart只测新宿主上的首次 request send;GFramework.Cqrs侧在每次 benchmark 前通过反射清空 dispatcher 静态缓存,避免把热缓存误当 first-hitColdStart_MediatR改为真正await完任务后再释放ServiceProvider,以满足Meziantou.Analyzer对资源生命周期的要求,并避免 benchmark 本身含有错误宿主释放语义
- 结论:
- 当前 benchmark 项目已经覆盖
Request、Notification、StreamRequest、RequestPipeline、RequestStartup - 后续若继续贴近
Mediatorcomparison benchmark,下一批最有价值的是 generated invoker provider、registration / service lifetime 与 concrete runtime 外部对照,而不是继续只加同层 steady-state case
- 当前 benchmark 项目已经覆盖
验证(RP-087)
dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release- 结果:通过,
0 warning / 0 error
- 结果:通过,
当前 stop-condition 度量(RP-087)
- primary metric:branch diff files vs
origin/main - 当前说明:提交前 branch diff 仍远低于
50文件阈值,可继续下一批 benchmark 或低风险 runtime 对照切片
当前下一步(RP-087)
- 提交本轮 request startup benchmark 后,继续扩展
GFramework.Cqrs.Benchmarks,优先评估 generated invoker provider 与 registration / service lifetime 矩阵 - 若要更贴近
Mediator的 comparison benchmark 设计哲学,评估是否在 benchmark 项目中同时接入Mediatorconcrete runtime 对照,而不只保留MediatR
阶段:request invoker reflection / generated 对照(CQRS-REWRITE-RP-088)
- 继续沿用
$gframework-batch-boot 50,当前 branch diff 相对origin/main仍明显低于阈值 - 本轮目标:不再只比较
GFramework.Cqrs与MediatR的外层框架差异,而是开始直接量化GFramework.Cqrs内部 reflection request binding 与 generated invoker provider 路径的 steady-state 差异 - 本轮新增:
GFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestInvokerBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/README.md中的 generated invoker 场景说明
- 设计取舍:
- 采用 benchmark 内手写的 generated registry/provider“等价物”,而不是当轮就把真实
GFramework.Cqrs.SourceGenerators接到 benchmark 项目中,目的是先走通真实的 registrar -> descriptor 预热 -> dispatcher generated path,同时把写入面控制在低风险范围 - generated 对照使用程序集级
CqrsHandlerRegistryAttribute+ICqrsRequestInvokerProvider+IEnumeratesCqrsRequestInvokerDescriptors,确保运行时语义与生产路径一致 - 在 benchmark 生命周期前后清理 dispatcher 静态缓存,避免 generated descriptor 预热状态跨场景泄漏,污染 reflection 对照
- 采用 benchmark 内手写的 generated registry/provider“等价物”,而不是当轮就把真实
- 结论:
- 当前 benchmark 项目已经能区分
GFramework.Cqrs的 reflection request 路径、generated request 路径与MediatR外部对照 - 后续若继续贴近
Mediatorcomparison benchmark,下一批更适合扩到 registration / service lifetime、stream generated provider,或再决定是否接入Mediatorconcrete runtime
- 当前 benchmark 项目已经能区分
验证(RP-088)
dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release- 结果:通过,
0 warning / 0 error
- 结果:通过,
当前 stop-condition 度量(RP-088)
- primary metric:branch diff files vs
origin/main - 当前说明:提交前 branch diff 仍远低于
50文件阈值,可继续推进下一批 benchmark 对照切片
当前下一步(RP-088)
- 提交本轮 request invoker benchmark 后,继续扩展
GFramework.Cqrs.Benchmarks,优先评估 registration / service lifetime 或 stream generated provider
阶段:stream invoker reflection / generated 对照(CQRS-REWRITE-RP-089)
- 使用
$gframework-batch-boot 30继续feat/cqrs-optimization的 CQRS 收口批次 - 本轮基线选择:
origin/main c01abac0,committer date2026-05-06 09:40:08 +0800main a8c6c11e,committer date2026-05-05 13:14:24 +0800
- 启动时 branch diff vs
origin/main为18files /2100lines,低于30文件阈值,因此继续选择单模块、低风险 benchmark 切片 - 复核
GFramework.Cqrs.Benchmarks与ai-libs/Mediator/benchmarks后确认:RP-088已把 generated descriptor 预热收益量化到 request dispatch 路径- stream benchmark 仍停留在 direct handler / reflection runtime /
MediatR三路对照,尚未量化 generated stream invoker provider 的收益 - 虽然
Mediator参考基准大量使用 service lifetime 矩阵,但当前GFramework.Cqrs.Benchmarks尚未建立对称的 scoped host 模式;直接扩 lifetime 会引入超出本批风险预算的宿主语义变化
- 本轮因此优先选择 request 对称切片,而不是 service lifetime 扩展:
- 新增
Messaging/StreamInvokerBenchmarks.cs - 新增
Messaging/GeneratedStreamInvokerBenchmarkRegistry.cs - 更新
GFramework.Cqrs.Benchmarks/README.md
- 新增
- 设计约束:
- 继续沿用 handwritten generated registry/provider 模式,避免把 benchmark 基础设施与真实 source-generator 输出耦合
- 复用与
RP-088相同的 dispatcher 缓存清理策略,确保 reflection / generated 路径对照不受静态缓存残留污染 - 使用统一的异步枚举体工厂,让三组 stream handler 共享同一枚举成本基线,把变量收敛到 invoker/provider 接线路径
当前下一步(RP-089)
- 完成本轮 benchmark 项目 Release build、license header 检查与 diff 校验后,更新 active tracking 的权威验证列表
- 若 branch diff 仍明显低于
30文件阈值,可继续评估 notification publish strategy 或更贴近Mediatorconcrete runtime 的单批对照 - 若要继续贴近
Mediator的 comparison benchmark 设计哲学,评估是否把Mediatorconcrete runtime 本身接入 benchmark 项目,而不是长期只保留MediatR
验证(RP-089)
dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release- 结果:通过,
0 warning / 0 error
- 结果:通过,
GIT_DIR=<worktree-git-dir> GIT_WORK_TREE=<worktree-root> python3 scripts/license-header.py --check- 结果:通过
git diff --check- 结果:通过
dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestStartupBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1- 结果:部分通过;
MediatRstartup benchmark 已恢复真实测量,ColdStart_GFrameworkCqrs仍因No CQRS request handler registered失败
- 结果:部分通过;