mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-06 16:16:44 +08:00
fix(cqrs): 收敛 benchmark review 收尾问题
- 修复 benchmark workflow 过滤器输入的 shell 注入风险 - 统一 request 与 stream invoker 基准中 MediatR handler 的生命周期基线 - 更新 request pipeline benchmark 的缓存清理与空行为类型声明 - 压缩 cqrs-rewrite active 跟踪与 trace,记录本轮 PR review 收尾结论
This commit is contained in:
parent
2cb6216d05
commit
6d619b9a1f
4
.github/workflows/benchmark.yml
vendored
4
.github/workflows/benchmark.yml
vendored
@ -53,10 +53,12 @@ jobs:
|
||||
|
||||
- name: Run filtered benchmarks
|
||||
if: ${{ inputs.benchmark_filter != '' }}
|
||||
env:
|
||||
BENCHMARK_FILTER: ${{ inputs.benchmark_filter }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- \
|
||||
--filter "${{ inputs.benchmark_filter }}"
|
||||
--filter "$BENCHMARK_FILTER"
|
||||
|
||||
- name: Upload BenchmarkDotNet artifacts
|
||||
if: ${{ always() && inputs.benchmark_filter != '' }}
|
||||
|
||||
@ -93,7 +93,7 @@ public class RequestInvokerBenchmarks
|
||||
configure: null,
|
||||
typeof(RequestInvokerBenchmarks),
|
||||
static candidateType => candidateType == typeof(MediatRBenchmarkRequestHandler),
|
||||
ServiceLifetime.Singleton);
|
||||
ServiceLifetime.Transient);
|
||||
_mediatr = _serviceProvider.GetRequiredService<IMediator>();
|
||||
}
|
||||
|
||||
|
||||
@ -64,6 +64,7 @@ public class RequestPipelineBenchmarks
|
||||
MinLevel = LogLevel.Fatal
|
||||
};
|
||||
Fixture.Setup("RequestPipeline", handlerCount: 1, pipelineCount: PipelineCount);
|
||||
BenchmarkDispatcherCacheHelper.ClearDispatcherCaches();
|
||||
|
||||
_baselineHandler = new BenchmarkRequestHandler();
|
||||
_container = BenchmarkHostFactory.CreateFrozenGFrameworkContainer(container =>
|
||||
@ -101,6 +102,7 @@ public class RequestPipelineBenchmarks
|
||||
public void Cleanup()
|
||||
{
|
||||
_serviceProvider.Dispose();
|
||||
BenchmarkDispatcherCacheHelper.ClearDispatcherCaches();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -261,20 +263,28 @@ public class RequestPipelineBenchmarks
|
||||
/// <summary>
|
||||
/// pipeline 行为槽位 1。
|
||||
/// </summary>
|
||||
public sealed class BenchmarkPipelineBehavior1 : BenchmarkPipelineBehaviorBase;
|
||||
public sealed class BenchmarkPipelineBehavior1 : BenchmarkPipelineBehaviorBase
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// pipeline 行为槽位 2。
|
||||
/// </summary>
|
||||
public sealed class BenchmarkPipelineBehavior2 : BenchmarkPipelineBehaviorBase;
|
||||
public sealed class BenchmarkPipelineBehavior2 : BenchmarkPipelineBehaviorBase
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// pipeline 行为槽位 3。
|
||||
/// </summary>
|
||||
public sealed class BenchmarkPipelineBehavior3 : BenchmarkPipelineBehaviorBase;
|
||||
public sealed class BenchmarkPipelineBehavior3 : BenchmarkPipelineBehaviorBase
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// pipeline 行为槽位 4。
|
||||
/// </summary>
|
||||
public sealed class BenchmarkPipelineBehavior4 : BenchmarkPipelineBehaviorBase;
|
||||
public sealed class BenchmarkPipelineBehavior4 : BenchmarkPipelineBehaviorBase
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ public class StreamInvokerBenchmarks
|
||||
configure: null,
|
||||
typeof(StreamInvokerBenchmarks),
|
||||
static candidateType => candidateType == typeof(MediatRBenchmarkStreamHandler),
|
||||
ServiceLifetime.Singleton);
|
||||
ServiceLifetime.Transient);
|
||||
_mediatr = _serviceProvider.GetRequiredService<IMediator>();
|
||||
}
|
||||
|
||||
|
||||
@ -31,10 +31,10 @@ CQRS 迁移与收敛。
|
||||
## 当前活跃事实
|
||||
|
||||
- 当前分支对应 `PR #326`,状态为 `OPEN`
|
||||
- latest-head review 已从 benchmark 运行级缺陷收敛到剩余文档入口与是否继续接受 benchmark 语义细化的判断
|
||||
- latest-head review 现仍有少量 open thread,但本地复核后,仍成立的问题已收敛到 benchmark 对照公平性、workflow 输入安全性与 active 文档压缩
|
||||
- benchmark 场景现统一通过 `BenchmarkHostFactory` 构建最小宿主:GFramework 侧在 runtime 分发前显式 `Freeze()` 容器,MediatR 侧只扫描当前场景需要的 handler / behavior 类型
|
||||
- `RequestStartupBenchmarks` 已恢复 `ColdStart_GFrameworkCqrs` 结果产出,不再命中 `No CQRS request handler registered`
|
||||
- 已新增手动触发的 benchmark workflow;默认只验证 benchmark 项目 Release build,只有显式提供过滤器时才执行 BenchmarkDotNet 运行
|
||||
- 已新增手动触发的 benchmark workflow;默认只验证 benchmark 项目 Release build,只有显式提供过滤器时才执行 BenchmarkDotNet 运行;过滤器输入现通过环境变量传入 shell,避免 workflow_dispatch 输入直接插值到命令行
|
||||
- 远端 `CTRF` 最新汇总为 `2274/2274` passed
|
||||
- `MegaLinter` 当前只暴露 `dotnet-format` 的 `Restore operation failed` 环境噪音,尚未提供本地仍成立的文件级格式诊断
|
||||
|
||||
@ -50,74 +50,12 @@ CQRS 迁移与收敛。
|
||||
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestStartupBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
|
||||
- 结果:通过
|
||||
- 备注:`ColdStart_GFrameworkCqrs` 已恢复出数,最新本地输出约 `220-292 us`,MediatR 对照约 `575-616 us`;当前仅剩 BenchmarkDotNet 对单次 cold-start 场景的 `MinIterationTime` 提示
|
||||
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
|
||||
- 结果:通过
|
||||
- 备注:确认冻结后的 GFramework 最小宿主与受限扫描的 MediatR 最小宿主均可完成 steady-state request 对照
|
||||
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
|
||||
- 结果:通过,`0 warning / 0 error`
|
||||
- 备注:用于验证新增手动 benchmark workflow 依赖的 benchmark 项目入口仍可在 Release 下编译
|
||||
- 备注:用于验证本轮 request invoker / pipeline / stream invoker 调整与 benchmark workflow 改动后的 Release 编译结果
|
||||
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json --json-output <temporary-json-output>`
|
||||
- 结果:通过
|
||||
- 备注:确认当前分支对应 `PR #326`,本轮剩余 open AI feedback 主要集中在 benchmark 对照语义与 `ai-plan` 结构收敛
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
|
||||
- `git diff --check`
|
||||
- 结果:通过
|
||||
- `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.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/2` passed
|
||||
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
|
||||
- 结果:通过,`0 warning / 0 error`
|
||||
- 备注:先后覆盖 `StreamingBenchmarks`、`RequestPipelineBenchmarks`、`RequestStartupBenchmarks`、`RequestInvokerBenchmarks` 与 `StreamInvokerBenchmarks` 的引入后复核
|
||||
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestStartupBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
|
||||
- 结果:部分通过
|
||||
- 备注:`Initialization_MediatR` 与 `ColdStart_MediatR` 已可实际运行;`ColdStart_GFrameworkCqrs` 仍因 `No CQRS request handler registered` 无法产出完整对照
|
||||
- `GIT_DIR=<worktree-git-dir> GIT_WORK_TREE=<worktree-root> python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行,避免脚本内部 plain `git ls-files` 误判仓库上下文
|
||||
- `git diff --check`
|
||||
- 结果:通过
|
||||
- `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/5` passed
|
||||
- `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/4` passed
|
||||
- `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` 后运行,避免脚本内部 plain `git ls-files` 误判仓库上下文
|
||||
- `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/1` passed
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
|
||||
- `git diff --check`
|
||||
- 结果:通过
|
||||
- `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/1` passed
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
|
||||
- `git diff --check`
|
||||
- 结果:通过
|
||||
- `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/4` passed
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
|
||||
- `git diff --check`
|
||||
- 结果:通过
|
||||
- `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/6` passed
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
|
||||
- `git diff --check`
|
||||
- 结果:通过
|
||||
- `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/7` passed
|
||||
- 备注:确认当前分支对应 `PR #326`,本轮剩余 open AI feedback 以 workflow 输入安全、benchmark 对照公平性与 active 文档压缩为主
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
|
||||
@ -126,9 +64,9 @@ CQRS 迁移与收敛。
|
||||
|
||||
## 下一推荐步骤
|
||||
|
||||
1. 继续处理 `PR #326` 的剩余 review 收尾,优先保持 benchmark 对照语义与 `ai-plan` active 入口一致
|
||||
2. 决定是否继续细化 `RequestStartupBenchmarks` 的 cold-start harness,降低 `InvocationCount=1` 带来的 `MinIterationTime` 提示噪音
|
||||
3. 若需要在 CI 中手动复核 benchmark,优先使用新增 workflow 的 `benchmark_filter` 输入按场景筛选,避免默认运行整个 benchmark 矩阵
|
||||
1. 重新运行 `$gframework-pr-review`,确认本轮 workflow / benchmark / active 文档修复是否已消化当前 latest-head open threads
|
||||
2. 若 `PR #326` 仍剩基准语义类反馈,优先判断它们属于真实对照偏差还是有意保留的 benchmark 设计取舍
|
||||
3. 若需要在 CI 中手动复核 benchmark,继续使用 workflow 的 `benchmark_filter` 输入按场景筛选,避免默认运行整个 benchmark 矩阵
|
||||
|
||||
## 活跃文档
|
||||
|
||||
|
||||
@ -44,6 +44,29 @@
|
||||
- 结果:通过
|
||||
- 备注:steady-state request 对照可正常运行,未再触发 MediatR 重复注册或 GFramework 首次解析失败
|
||||
|
||||
### 阶段:PR #326 review 收尾补丁(CQRS-REWRITE-RP-090)
|
||||
|
||||
- 再次使用 `$gframework-pr-review` 复核 `PR #326` latest-head open threads 后,主线程确认本轮仍成立且适合在当前 PR 内收敛的问题集中在四类:
|
||||
- `.github/workflows/benchmark.yml` 的 `benchmark_filter` 直接插值到 shell,存在 workflow_dispatch 输入注入风险
|
||||
- `RequestInvokerBenchmarks` 与 `StreamInvokerBenchmarks` 的 MediatR handler 生命周期仍为 `Singleton`,与 GFramework 反射 / generated 路径的 transient 语义不一致
|
||||
- `RequestPipelineBenchmarks` 未在场景切换前后清理 dispatcher 缓存,且四个空 pipeline behavior 类型仍使用非法的分号类声明
|
||||
- `ai-plan/public/cqrs-rewrite` active 文档仍保留旧失败结论与重复日期标题,和“active 入口只保留最新权威恢复点”的约束不一致
|
||||
- 本轮刻意未扩展处理的 review:
|
||||
- `MicrosoftDiContainer` 的释放契约建议会扩大到核心 Ioc 接口与全仓库生命周期语义,不适合作为 benchmark review 顺手改动
|
||||
- `RequestStartupBenchmarks` 的“手工单点注册 vs 受限程序集扫描”差异目前属于有意保留的最小宿主模型,代码注释已明确该设计边界
|
||||
- 已修改:
|
||||
- `.github/workflows/benchmark.yml`
|
||||
- `GFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.cs`
|
||||
- `GFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.cs`
|
||||
- `GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs`
|
||||
- `ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md`
|
||||
- `ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
|
||||
- 预期结果:
|
||||
- 手动 benchmark workflow 的过滤器输入不再直接参与 shell 解析
|
||||
- request / stream invoker 三路对照的 handler 生命周期重新回到同一基线
|
||||
- request pipeline benchmark 在 `0 / 1 / 4` 场景切换时不再复用旧 dispatcher cache
|
||||
- active tracking / trace 更符合 boot 恢复入口所要求的“只保留最新权威结论”形状
|
||||
|
||||
## 2026-04-30
|
||||
|
||||
### 阶段:历史 PR #307 active 入口收敛(CQRS-REWRITE-RP-076)
|
||||
@ -257,7 +280,7 @@
|
||||
1. 若 review 重新触发后仍有 latest-head open thread,继续以 `PR #323` 为当前唯一 PR 恢复锚点复核
|
||||
2. 后续若继续推进代码切片,优先复核基础 generation gate 之外的 runtime contract 或 fallback selection 分支
|
||||
|
||||
## 2026-05-06
|
||||
## 2026-05-06(RP-083 ~ RP-089)
|
||||
|
||||
### 阶段:mixed invoker provider 排序回归(CQRS-REWRITE-RP-083)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user