diff --git a/GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs b/GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs index de3c7b92..80ce9b88 100644 --- a/GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs +++ b/GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs @@ -95,6 +95,7 @@ public class NotificationBenchmarks /// /// 通过 GFramework.CQRS runtime 发布 notification。 /// + /// 代表当前 GFramework.CQRS publish 完成的值任务。 [Benchmark(Baseline = true)] public ValueTask PublishNotification_GFrameworkCqrs() { @@ -104,6 +105,7 @@ public class NotificationBenchmarks /// /// 通过 MediatR 发布 notification,作为外部设计对照。 /// + /// 代表当前 MediatR publish 完成的任务。 [Benchmark] public Task PublishNotification_MediatR() { @@ -113,6 +115,7 @@ public class NotificationBenchmarks /// /// 通过 `Mediator` source-generated concrete mediator 发布 notification,作为高性能对照组。 /// + /// 代表当前 `Mediator` publish 完成的值任务。 [Benchmark] public ValueTask PublishNotification_Mediator() { diff --git a/GFramework.Cqrs.Benchmarks/Messaging/NotificationFanOutBenchmarks.cs b/GFramework.Cqrs.Benchmarks/Messaging/NotificationFanOutBenchmarks.cs index 431fa359..0e3efb1a 100644 --- a/GFramework.Cqrs.Benchmarks/Messaging/NotificationFanOutBenchmarks.cs +++ b/GFramework.Cqrs.Benchmarks/Messaging/NotificationFanOutBenchmarks.cs @@ -123,6 +123,7 @@ public class NotificationFanOutBenchmarks /// /// 直接依次调用 4 个处理器,作为 fan-out dispatch 额外开销的 baseline。 /// + /// 代表基线顺序调用 4 个处理器完成当前 notification 处理的值任务。 [Benchmark(Baseline = true)] public async ValueTask PublishNotification_Baseline() { @@ -135,6 +136,7 @@ public class NotificationFanOutBenchmarks /// /// 通过默认顺序发布器的 GFramework.CQRS runtime 发布固定 4 处理器的 notification。 /// + /// 代表当前默认顺序发布器 publish 完成的值任务。 [Benchmark] public ValueTask PublishNotification_GFrameworkCqrsSequential() { @@ -144,6 +146,7 @@ public class NotificationFanOutBenchmarks /// /// 通过内置 Task.WhenAll(...) 发布器的 GFramework.CQRS runtime 发布固定 4 处理器的 notification。 /// + /// 代表当前 Task.WhenAll(...) 发布器 publish 完成的值任务。 [Benchmark] public ValueTask PublishNotification_GFrameworkCqrsTaskWhenAll() { @@ -153,6 +156,7 @@ public class NotificationFanOutBenchmarks /// /// 通过 MediatR 发布固定 4 处理器的 notification,作为外部设计对照。 /// + /// 代表当前 MediatR publish 完成的任务。 [Benchmark] public Task PublishNotification_MediatR() { @@ -162,6 +166,7 @@ public class NotificationFanOutBenchmarks /// /// 通过 `Mediator` source-generated concrete mediator 发布固定 4 处理器的 notification,作为高性能对照组。 /// + /// 代表当前 `Mediator` publish 完成的值任务。 [Benchmark] public ValueTask PublishNotification_Mediator() { diff --git a/GFramework.Cqrs.Benchmarks/Messaging/RequestStartupBenchmarks.cs b/GFramework.Cqrs.Benchmarks/Messaging/RequestStartupBenchmarks.cs index 2c685fed..a32acc26 100644 --- a/GFramework.Cqrs.Benchmarks/Messaging/RequestStartupBenchmarks.cs +++ b/GFramework.Cqrs.Benchmarks/Messaging/RequestStartupBenchmarks.cs @@ -97,6 +97,7 @@ public class RequestStartupBenchmarks /// /// 返回已构建宿主中的 MediatR mediator,作为 initialization 组的句柄解析 baseline。 /// + /// 当前 benchmark 复用的 MediatR mediator。 [Benchmark(Baseline = true)] [BenchmarkCategory("Initialization")] public IMediator Initialization_MediatR() @@ -107,6 +108,7 @@ public class RequestStartupBenchmarks /// /// 返回已构建宿主中的 GFramework.CQRS runtime,确保与 MediatR baseline 处于相同初始化阶段。 /// + /// 当前 benchmark 复用的 GFramework.CQRS runtime。 [Benchmark] [BenchmarkCategory("Initialization")] public ICqrsRuntime Initialization_GFrameworkCqrs() @@ -117,6 +119,7 @@ public class RequestStartupBenchmarks /// /// 返回已构建宿主中的 `Mediator` concrete mediator,作为 source-generated 对照组的初始化句柄。 /// + /// 当前 benchmark 复用的 `Mediator` concrete mediator。 [Benchmark] [BenchmarkCategory("Initialization")] public GeneratedMediator Initialization_Mediator() @@ -127,6 +130,7 @@ public class RequestStartupBenchmarks /// /// 在新宿主上首次发送 request,作为 MediatR 的 cold-start baseline。 /// + /// 当前 request 的响应结果。 [Benchmark(Baseline = true)] [BenchmarkCategory("ColdStart")] public async Task ColdStart_MediatR() @@ -139,6 +143,7 @@ public class RequestStartupBenchmarks /// /// 在新 runtime 上首次发送 request,量化 GFramework.CQRS 的 first-hit 成本。 /// + /// 当前 request 的响应结果。 [Benchmark] [BenchmarkCategory("ColdStart")] public async ValueTask ColdStart_GFrameworkCqrs() @@ -151,6 +156,7 @@ public class RequestStartupBenchmarks /// /// 在新的 `Mediator` 宿主上首次发送 request,量化 source-generated concrete path 的 cold-start 成本。 /// + /// 当前 request 的响应结果。 [Benchmark] [BenchmarkCategory("ColdStart")] public async ValueTask ColdStart_Mediator() diff --git a/GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs b/GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs index 34788522..76ad5831 100644 --- a/GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs +++ b/GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs @@ -143,6 +143,7 @@ public class StreamInvokerBenchmarks /// /// 直接调用最小 stream handler,并按当前观测模式消费 stream,作为 dispatch 额外开销 baseline。 /// + /// 代表基线 stream 按当前观测模式消费完成的值任务。 [Benchmark(Baseline = true)] public ValueTask Stream_Baseline() { @@ -152,6 +153,7 @@ public class StreamInvokerBenchmarks /// /// 通过 GFramework.CQRS 反射 stream binding 路径创建 stream,并按当前观测模式消费。 /// + /// 代表当前 GFramework.CQRS 反射 stream 按观测模式消费完成的值任务。 [Benchmark] public ValueTask Stream_GFrameworkReflection() { @@ -166,6 +168,7 @@ public class StreamInvokerBenchmarks /// /// 通过 generated stream invoker provider 预热后的 GFramework.CQRS runtime 创建 stream,并按当前观测模式消费。 /// + /// 代表当前 GFramework.CQRS generated stream 按观测模式消费完成的值任务。 [Benchmark] public ValueTask Stream_GFrameworkGenerated() { @@ -180,6 +183,7 @@ public class StreamInvokerBenchmarks /// /// 通过 MediatR 创建 stream,并按当前观测模式消费,作为外部对照。 /// + /// 代表当前 MediatR stream 按观测模式消费完成的值任务。 [Benchmark] public ValueTask Stream_MediatR() { diff --git a/GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs b/GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs index 7dbb5d78..f1606018 100644 --- a/GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs +++ b/GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs @@ -148,6 +148,7 @@ public class StreamLifetimeBenchmarks /// /// 直接调用 handler,并按当前观测模式消费 stream,作为不同生命周期矩阵下的 dispatch 额外开销 baseline。 /// + /// 代表基线 handler stream 按当前观测模式消费完成的值任务。 [Benchmark(Baseline = true)] public ValueTask Stream_Baseline() { @@ -157,6 +158,7 @@ public class StreamLifetimeBenchmarks /// /// 通过 GFramework.CQRS reflection stream binding 路径创建 stream,并按当前观测模式消费。 /// + /// 代表当前 reflection stream 按当前观测模式消费完成的值任务。 [Benchmark] public ValueTask Stream_GFrameworkReflection() { @@ -183,6 +185,7 @@ public class StreamLifetimeBenchmarks /// /// 通过 generated stream invoker provider 预热后的 GFramework.CQRS runtime 创建 stream,并按当前观测模式消费。 /// + /// 代表当前 generated stream 按当前观测模式消费完成的值任务。 [Benchmark] public ValueTask Stream_GFrameworkGenerated() { @@ -209,6 +212,7 @@ public class StreamLifetimeBenchmarks /// /// 通过 MediatR 创建 stream,并按当前观测模式消费,作为外部对照。 /// + /// 代表当前 MediatR stream 按当前观测模式消费完成的值任务。 [Benchmark] public ValueTask Stream_MediatR() { diff --git a/GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs b/GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs index 24ea79bd..449c1bba 100644 --- a/GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs +++ b/GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs @@ -145,6 +145,7 @@ public class StreamingBenchmarks /// /// 通过 GFramework.CQRS runtime 创建 stream,并按当前观测模式消费。 /// + /// 按当前观测模式完成 stream 消费后的等待句柄。 [Benchmark] public ValueTask Stream_GFrameworkCqrs() { diff --git a/ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md b/ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md index e7fcb3b0..eb3cd91f 100644 --- a/ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md +++ b/ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md @@ -12,7 +12,7 @@ CQRS 迁移与收敛。 ## 当前恢复点 -- 恢复点编号:`CQRS-REWRITE-RP-137` +- 恢复点编号:`CQRS-REWRITE-RP-138` - 当前阶段:`Phase 8` - 当前 PR 锚点:`PR #349(已于 2026-05-12 合并到 origin/main)` - 当前结论: @@ -27,6 +27,17 @@ CQRS 迁移与收敛。 - 本轮继续按 `$gframework-batch-boot 50` 协调 subagent,围绕 benchmark 文档与 startup parity 做两波窄切片: - 已提交 `f346110a`:`StreamStartupBenchmarks` 补 `Mediator` startup parity - 待收尾提交:`StreamingBenchmarks` 的 XML 文档补齐与 `GFramework.Cqrs.Benchmarks/README.md` 的 stream startup / gap 同步 + - 在当前恢复点继续推进第 2 波 benchmark XML 契约收口,范围严格限定为公开 benchmark 方法缺失的 `` 文档: + - 主线程:`StreamingBenchmarks.cs`、`NotificationBenchmarks.cs` 与 `ai-plan/public/cqrs-rewrite/**` + - worker:`StreamLifetimeBenchmarks.cs`、`StreamInvokerBenchmarks.cs`、`NotificationFanOutBenchmarks.cs` + - 启动第 2 波前,当前分支相对 `origin/main @ 2b2bec65 (2026-05-12 11:49:39 +0800)` 的已提交 branch diff 为 `5 files / 177 lines`,远低于 `$gframework-batch-boot 50` 的文件阈值;本轮是否继续主要由 context-budget / reviewability 决定,而不是 branch-size 预算。 + - 第 3 波继续沿同一模式扩到 request 系 benchmark XML 契约收口,并已由 worker 分别提交: + - `555c7c07`:`RequestBenchmarks.cs`、`RequestPipelineBenchmarks.cs` + - `ab422b05`:`RequestInvokerBenchmarks.cs`、`RequestLifetimeBenchmarks.cs` + - 另有 `RequestStartupBenchmarks.cs` 已完成 `` 收口,待与主线程未提交切片一并收尾 + - 当前已决定在第 3 波后停在自然边界,而不是继续开启第 4 波: + - branch-size 仍远低于 `50 files` + - 但剩余候选已不比当前波次更低风险,继续机械扩批会降低 reviewability,并推高当前上下文负担 - tests 侧此前已补齐并提交: - `CqrsRegistrationServiceTests`:补空输入、空项过滤、稳定键排序与跨调用跳过边界 - `CqrsHandlerRegistrarTests` 与 `CqrsHandlerRegistrarFallbackFailureTests`: @@ -44,6 +55,11 @@ CQRS 迁移与收敛。 - 当前分支:`feat/cqrs-optimization` - 当前 PR:`PR #349(已合并;当前分支暂无新的公开 PR)` - 当前写面: + - `GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs` + - `GFramework.Cqrs.Benchmarks/Messaging/NotificationFanOutBenchmarks.cs` + - `GFramework.Cqrs.Benchmarks/Messaging/RequestStartupBenchmarks.cs` + - `GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs` + - `GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs` - `GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs` - `GFramework.Cqrs.Benchmarks/Messaging/StreamStartupBenchmarks.cs` - `GFramework.Cqrs.Benchmarks/README.md` @@ -51,16 +67,19 @@ CQRS 迁移与收敛。 - `ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md` - 当前基线: - `origin/main @ 2b2bec65 (2026-05-12 11:49:39 +0800)` - - 当前已提交 branch diff:`1 file / 60 lines` - - 当前工作树尚有 2 个未提交收尾文件:`StreamingBenchmarks.cs`、`GFramework.Cqrs.Benchmarks/README.md` + - 当前已提交 branch diff:`9 files / 143 lines` + - 当前分支比 `origin/main` 多 `4` 个提交:`f346110a`、`a016e3d4`、`ab422b05`、`555c7c07` + - 当前未提交面由 notification / stream / request-startup 的 XML 契约补齐与 `ai-plan` 恢复点更新构成 - 本轮提交: - `f346110a` `feat(cqrs-benchmarks): 补齐 stream startup 的 Mediator 对照路径` + - `ab422b05` `docs(cqrs-benchmarks): 补齐 request benchmark 返回值注释` + - `555c7c07` `docs(cqrs-benchmarks): 补齐 request benchmark 返回值文档` ## 当前风险 - `StreamStartupBenchmarks` 的 `Mediator` parity 目前只做了编译验证,尚未单独执行 benchmark 作业确认 startup 矩阵运行结果。 - `StreamLifetimeBenchmarks` 仍缺 `Mediator` parity;该项涉及 `BenchmarkHostFactory` 与 compile-time lifetime 形状,不再是本轮低风险切片。 -- 当前 worktree 仍有 2 个未提交文档/注释收尾文件;若不在同轮提交,下一次 `boot` 会同时面对已提交 benchmark 扩展与未提交文档漂移。 +- 本轮已在 request 系 benchmark XML 契约收口后主动停批次;若后续恢复,优先先提交当前未提交面,再决定是否开启 docs/README 或 smoke-run 下一阶段,而不是继续机械扩张 XML 批次。 ## 最近权威验证 @@ -73,9 +92,10 @@ CQRS 迁移与收敛。 ## 下一推荐步骤 -1. 先提交 `StreamingBenchmarks.cs`、`GFramework.Cqrs.Benchmarks/README.md` 与本 tracking / trace 收尾,回到干净工作树。 -2. 若继续 benchmark 波次,优先单独执行 `StreamStartupBenchmarks` 的最小 smoke run,验证新加 `Mediator` startup 路径可运行。 -3. 若后续还要扩 stream parity,把 `StreamLifetimeBenchmarks` 视为跨文件设计任务,而不是继续按“单文件低风险切片”处理。 +1. 串行运行 `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`、`python3 scripts/license-header.py --check --paths ...` 与 `git diff --check`,作为当前自然停点的权威收尾验证。 +2. 提交当前未提交的 notification / stream / request-startup XML 契约与 `ai-plan` 更新,回到干净工作树。 +3. 若后续继续 benchmark 波次,优先单独执行 `StreamStartupBenchmarks` 的最小 smoke run,验证新加 `Mediator` startup 路径可运行。 +4. 若后续还要扩 stream parity,把 `StreamLifetimeBenchmarks` 视为跨文件设计任务,而不是继续按“单文件低风险切片”处理。 ## 活跃文档 diff --git a/ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md b/ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md index 81baa47e..88f20d7e 100644 --- a/ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md +++ b/ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md @@ -7,6 +7,69 @@ SPDX-License-Identifier: Apache-2.0 ## 2026-05-12 +### 阶段:benchmark XML 契约第 2 波收口(CQRS-REWRITE-RP-138) + +- 延续 `$gframework-batch-boot 50`,基线保持为 `origin/main @ 2b2bec65 (2026-05-12 11:49:39 +0800)`。 +- 第 2 波启动前,当前分支相对基线的已提交 branch diff 为 `5 files / 177 lines`,明显低于 `50 files` 阈值;本轮继续与否的主停止信号仍是 context-budget / reviewability。 +- 主线程本地盘点 `GFramework.Cqrs.Benchmarks/Messaging/*.cs` 的公开 `[Benchmark]` 方法后,确认当前仍有一批与既有收口模式一致的 XML `` 缺口: + - `StreamingBenchmarks.Stream_GFrameworkCqrs()` + - `NotificationBenchmarks` 的 3 个公开 benchmark 方法 + - `NotificationFanOutBenchmarks` 的 5 个公开 benchmark 方法 + - `StreamInvokerBenchmarks` 的 4 个公开 benchmark 方法 + - `StreamLifetimeBenchmarks` 的 4 个公开 benchmark 方法 +- 本波 accepted ownership: + - 主线程 + - `GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs` + - `GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs` + - `ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md` + - `ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md` + - worker + - `StreamLifetimeBenchmarks.cs` + - `StreamInvokerBenchmarks.cs` + - `NotificationFanOutBenchmarks.cs` +- worker 回传验收结论: + - `StreamLifetimeBenchmarks.cs` + - 只补 `Stream_Baseline`、`Stream_GFrameworkReflection`、`Stream_GFrameworkGenerated`、`Stream_MediatR` 的 `` + - worker 自报 `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release` 通过 + - `StreamInvokerBenchmarks.cs` + - 只补 4 个公开 benchmark 方法的 `` + - worker 自报同一条 benchmark 工程 build 通过 + - `NotificationFanOutBenchmarks.cs` + - 只补 5 个公开 benchmark 方法的 `` + - worker 自报 build 遇到 `CS2012`:`obj/Release/net10.0/GFramework.Cqrs.Benchmarks.dll` 被并发进程占用;该失败被判定为并发构建噪音,而不是代码语义问题 +- 主线程局部实施: + - `StreamingBenchmarks.cs` + - 为 `Stream_GFrameworkCqrs()` 补 `` + - `NotificationBenchmarks.cs` + - 为 `PublishNotification_GFrameworkCqrs()`、`PublishNotification_MediatR()`、`PublishNotification_Mediator()` 补 `` +- 当前下一步: + - 主线程串行执行 benchmark 工程 Release build,消除 worker 并发写 `obj/Release` 带来的验证噪音 + - 若串行验证通过,决定是在当前自然停点提交收尾,还是继续 request 侧 XML 契约的下一波低风险批处理 + +### 阶段:request benchmark XML 契约第 3 波收口后停在自然边界(CQRS-REWRITE-RP-138) + +- 第 2 波串行验证通过后,继续用 3 个 worker 扩展 request 系 benchmark 的同类 `` 收口: + - `RequestStartupBenchmarks.cs` + - `RequestBenchmarks.cs` + `RequestPipelineBenchmarks.cs` + - `RequestInvokerBenchmarks.cs` + `RequestLifetimeBenchmarks.cs` +- worker 回传与 acceptance: + - `RequestStartupBenchmarks.cs` + - 只补公开 benchmark 方法缺失的 `` + - worker 自报 `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release` 通过 + - `RequestBenchmarks.cs` + `RequestPipelineBenchmarks.cs` + - 只补公开 benchmark 方法缺失的 `` + - worker 自报 build 通过,并已提交:`555c7c07 docs(cqrs-benchmarks): 补齐 request benchmark 返回值文档` + - `RequestInvokerBenchmarks.cs` + `RequestLifetimeBenchmarks.cs` + - 只补公开 benchmark 方法缺失的 `` + - worker 自报 build 通过,并已提交:`ab422b05 docs(cqrs-benchmarks): 补齐 request benchmark 返回值注释` +- 第 3 波后主线程 stop decision: + - 不再开启第 4 波 XML 契约批处理 + - 原因不是 branch-size 阈值耗尽;当前分支相对 `origin/main` 仍只有 `9 files / 143 lines` + - 停止原因是 context-budget / reviewability:剩余候选已不比当前波次更低风险,继续机械扩批收益下降 +- 当前下一步: + - 只做主线程未提交面的串行验证与收尾提交 + - 将干净工作树作为下一次 `boot` 的默认恢复目标 + ### 阶段:stream startup parity 与文档收尾(CQRS-REWRITE-RP-137) - 按 `$gframework-batch-boot 50` 恢复后,先重新执行 `$gframework-pr-review`。