mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-12 22:03:30 +08:00
feat(cqrs-benchmarks): 补齐request生命周期的Mediator对照
- 新增 RequestLifetimeBenchmarks 的 Mediator lifetime parity,并按编译期常量分支生成 Singleton、Scoped、Transient 宿主 - 更新 benchmark README 的 request lifetime coverage 与当前缺口说明,使其反映最新对照矩阵 - 修复 RequestBenchmarks 与 NotificationBenchmarks 的 XML 文档漂移,并同步 ai-plan 恢复点与验证结论
This commit is contained in:
parent
092946e91a
commit
e3532fc2c8
@ -21,7 +21,7 @@ using GeneratedMediator = Mediator.Mediator;
|
||||
namespace GFramework.Cqrs.Benchmarks.Messaging;
|
||||
|
||||
/// <summary>
|
||||
/// 对比单处理器 notification 在 GFramework.CQRS 与 MediatR 之间的 publish 开销。
|
||||
/// 对比单处理器 notification 在 GFramework.CQRS、NuGet `Mediator` 与 MediatR 之间的 publish 开销。
|
||||
/// </summary>
|
||||
[Config(typeof(Config))]
|
||||
public class NotificationBenchmarks
|
||||
@ -132,7 +132,7 @@ public class NotificationBenchmarks
|
||||
MediatR.INotification;
|
||||
|
||||
/// <summary>
|
||||
/// 同时实现 GFramework.CQRS 与 MediatR 契约的最小 notification handler。
|
||||
/// 同时实现 GFramework.CQRS、NuGet `Mediator` 与 MediatR 契约的最小 notification handler。
|
||||
/// </summary>
|
||||
public sealed class BenchmarkNotificationHandler :
|
||||
GFramework.Cqrs.Abstractions.Cqrs.INotificationHandler<BenchmarkNotification>,
|
||||
|
||||
@ -157,7 +157,7 @@ public class RequestBenchmarks
|
||||
public sealed record BenchmarkResponse(Guid Id);
|
||||
|
||||
/// <summary>
|
||||
/// 同时实现 GFramework.CQRS 与 MediatR 契约的最小 request handler。
|
||||
/// 同时实现 GFramework.CQRS、NuGet `Mediator` 与 MediatR 契约的最小 request handler。
|
||||
/// </summary>
|
||||
public sealed class BenchmarkRequestHandler :
|
||||
GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<BenchmarkRequest, BenchmarkResponse>,
|
||||
|
||||
@ -16,6 +16,7 @@ using GFramework.Core.Logging;
|
||||
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using GeneratedMediator = Mediator.Mediator;
|
||||
|
||||
namespace GFramework.Cqrs.Benchmarks.Messaging;
|
||||
|
||||
@ -35,7 +36,9 @@ public class RequestLifetimeBenchmarks
|
||||
private ScopedBenchmarkContainer? _scopedContainer;
|
||||
private ICqrsRuntime? _scopedRuntime;
|
||||
private ServiceProvider _serviceProvider = null!;
|
||||
private ServiceProvider _mediatorServiceProvider = null!;
|
||||
private IMediator? _mediatr;
|
||||
private GeneratedMediator? _mediator;
|
||||
private BenchmarkRequestHandler _baselineHandler = null!;
|
||||
private BenchmarkRequest _request = null!;
|
||||
private ILogger _runtimeLogger = null!;
|
||||
@ -83,7 +86,7 @@ public class RequestLifetimeBenchmarks
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建当前生命周期下的 GFramework 与 MediatR request 对照宿主。
|
||||
/// 构建当前生命周期下的 GFramework、NuGet `Mediator` 与 MediatR request 对照宿主。
|
||||
/// </summary>
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
@ -130,6 +133,12 @@ public class RequestLifetimeBenchmarks
|
||||
{
|
||||
_mediatr = _serviceProvider.GetRequiredService<IMediator>();
|
||||
}
|
||||
|
||||
_mediatorServiceProvider = CreateMediatorServiceProvider(Lifetime);
|
||||
if (Lifetime != HandlerLifetime.Scoped)
|
||||
{
|
||||
_mediator = _mediatorServiceProvider.GetRequiredService<GeneratedMediator>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -140,7 +149,7 @@ public class RequestLifetimeBenchmarks
|
||||
{
|
||||
try
|
||||
{
|
||||
BenchmarkCleanupHelper.DisposeAll(_container, _serviceProvider);
|
||||
BenchmarkCleanupHelper.DisposeAll(_container, _serviceProvider, _mediatorServiceProvider);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -196,6 +205,24 @@ public class RequestLifetimeBenchmarks
|
||||
return _mediatr!.Send(_request, CancellationToken.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过 `Mediator` source-generated concrete mediator 发送 request,作为 compile-time 对照。
|
||||
/// </summary>
|
||||
/// <returns>代表当前 `Mediator` request dispatch 完成的值任务。</returns>
|
||||
[Benchmark]
|
||||
public ValueTask<BenchmarkResponse> SendRequest_Mediator()
|
||||
{
|
||||
if (Lifetime == HandlerLifetime.Scoped)
|
||||
{
|
||||
return SendScopedMediatorRequestAsync(
|
||||
_mediatorServiceProvider,
|
||||
_request,
|
||||
CancellationToken.None);
|
||||
}
|
||||
|
||||
return _mediator!.Send(_request, CancellationToken.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按生命周期把 benchmark request handler 注册到 GFramework 容器。
|
||||
/// </summary>
|
||||
@ -243,12 +270,83 @@ public class RequestLifetimeBenchmarks
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建只承载当前 benchmark request handler 的最小 `Mediator` 对照宿主,并按生命周期切换生成器注册形状。
|
||||
/// </summary>
|
||||
/// <param name="lifetime">待比较的 handler 生命周期。</param>
|
||||
/// <returns>可直接解析 generated `Mediator.Mediator` 的 DI 宿主。</returns>
|
||||
private static ServiceProvider CreateMediatorServiceProvider(HandlerLifetime lifetime)
|
||||
{
|
||||
return lifetime switch
|
||||
{
|
||||
HandlerLifetime.Singleton => CreateSingletonMediatorServiceProvider(),
|
||||
HandlerLifetime.Scoped => CreateScopedMediatorServiceProvider(),
|
||||
HandlerLifetime.Transient => CreateTransientMediatorServiceProvider(),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(lifetime), lifetime, "Unsupported benchmark handler lifetime.")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在真实的 request 级作用域内执行一次 `Mediator` request 分发。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">请求响应类型。</typeparam>
|
||||
/// <param name="rootServiceProvider">当前 benchmark 的根 <see cref="ServiceProvider" />。</param>
|
||||
/// <param name="request">要发送的 request。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>当前 request 的响应结果。</returns>
|
||||
private static async ValueTask<TResponse> SendScopedMediatorRequestAsync<TResponse>(
|
||||
ServiceProvider rootServiceProvider,
|
||||
Mediator.IRequest<TResponse> request,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(rootServiceProvider);
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
|
||||
using var scope = rootServiceProvider.CreateScope();
|
||||
var mediator = scope.ServiceProvider.GetRequiredService<GeneratedMediator>();
|
||||
return await mediator.Send(request, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建 singleton 生命周期的 `Mediator` 对照宿主。
|
||||
/// </summary>
|
||||
/// <returns>按 singleton 形状生成 DI 注册的 `Mediator` 宿主。</returns>
|
||||
private static ServiceProvider CreateSingletonMediatorServiceProvider()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddMediator(static options => options.ServiceLifetime = ServiceLifetime.Singleton);
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建 scoped 生命周期的 `Mediator` 对照宿主。
|
||||
/// </summary>
|
||||
/// <returns>按 scoped 形状生成 DI 注册的 `Mediator` 宿主。</returns>
|
||||
private static ServiceProvider CreateScopedMediatorServiceProvider()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddMediator(static options => options.ServiceLifetime = ServiceLifetime.Scoped);
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建 transient 生命周期的 `Mediator` 对照宿主。
|
||||
/// </summary>
|
||||
/// <returns>按 transient 形状生成 DI 注册的 `Mediator` 宿主。</returns>
|
||||
private static ServiceProvider CreateTransientMediatorServiceProvider()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddMediator(static options => options.ServiceLifetime = ServiceLifetime.Transient);
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Benchmark request。
|
||||
/// </summary>
|
||||
/// <param name="Id">请求标识。</param>
|
||||
public sealed record BenchmarkRequest(Guid Id) :
|
||||
GFramework.Cqrs.Abstractions.Cqrs.IRequest<BenchmarkResponse>,
|
||||
Mediator.IRequest<BenchmarkResponse>,
|
||||
MediatR.IRequest<BenchmarkResponse>;
|
||||
|
||||
/// <summary>
|
||||
@ -258,10 +356,11 @@ public class RequestLifetimeBenchmarks
|
||||
public sealed record BenchmarkResponse(Guid Id);
|
||||
|
||||
/// <summary>
|
||||
/// 同时实现 GFramework.CQRS 与 MediatR 契约的最小 request handler。
|
||||
/// 同时实现 GFramework.CQRS、NuGet `Mediator` 与 MediatR 契约的最小 request handler。
|
||||
/// </summary>
|
||||
public sealed class BenchmarkRequestHandler :
|
||||
GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<BenchmarkRequest, BenchmarkResponse>,
|
||||
Mediator.IRequestHandler<BenchmarkRequest, BenchmarkResponse>,
|
||||
MediatR.IRequestHandler<BenchmarkRequest, BenchmarkResponse>
|
||||
{
|
||||
/// <summary>
|
||||
@ -272,6 +371,16 @@ public class RequestLifetimeBenchmarks
|
||||
return ValueTask.FromResult(new BenchmarkResponse(request.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理 NuGet `Mediator` request。
|
||||
/// </summary>
|
||||
ValueTask<BenchmarkResponse> Mediator.IRequestHandler<BenchmarkRequest, BenchmarkResponse>.Handle(
|
||||
BenchmarkRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Handle(request, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理 MediatR request。
|
||||
/// </summary>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
- `Messaging/RequestBenchmarks.cs`
|
||||
- direct handler、默认 `GFramework.Cqrs` runtime、NuGet `Mediator` source-generated concrete path、`MediatR`
|
||||
- `Messaging/RequestLifetimeBenchmarks.cs`
|
||||
- `Singleton / Scoped / Transient` 三类 handler 生命周期下,baseline、默认 generated-provider 宿主接线的 `GFramework.Cqrs` runtime 与 `MediatR`
|
||||
- `Singleton / Scoped / Transient` 三类 handler 生命周期下,baseline、默认 generated-provider 宿主接线的 `GFramework.Cqrs` runtime、NuGet `Mediator` source-generated concrete path 与 `MediatR`
|
||||
- `Messaging/RequestPipelineBenchmarks.cs`
|
||||
- `0 / 1 / 4` 个 pipeline 行为下,baseline、默认 generated-provider 宿主接线的 `GFramework.Cqrs` runtime 与 `MediatR`
|
||||
- `Messaging/RequestInvokerBenchmarks.cs`
|
||||
@ -104,5 +104,4 @@ dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.cspro
|
||||
## 当前缺口
|
||||
|
||||
- 当前没有 stream 生命周期版的 NuGet `Mediator` source-generated concrete path 对照;`StreamLifetimeBenchmarks` 现在只覆盖 `GFramework.Cqrs` 与 `MediatR`
|
||||
- 当前没有 request 生命周期下的 NuGet `Mediator` compile-time lifetime 矩阵;`RequestLifetimeBenchmarks` 只覆盖 `GFramework.Cqrs` 与 `MediatR`
|
||||
- 当前没有 notification fan-out 的生命周期矩阵;`NotificationFanOutBenchmarks` 只覆盖固定 `4 handler` 的已装配宿主
|
||||
|
||||
@ -12,7 +12,7 @@ CQRS 迁移与收敛。
|
||||
|
||||
## 当前恢复点
|
||||
|
||||
- 恢复点编号:`CQRS-REWRITE-RP-139`
|
||||
- 恢复点编号:`CQRS-REWRITE-RP-140`
|
||||
- 当前阶段:`Phase 8`
|
||||
- 当前 PR 锚点:`PR #349(已于 2026-05-12 合并到 origin/main)`
|
||||
- 当前结论:
|
||||
@ -23,14 +23,14 @@ CQRS 迁移与收敛。
|
||||
- README 一致性盘点成立,`GFramework.Cqrs.Benchmarks/README.md` 的 startup coverage / 解释边界仍可收紧
|
||||
- benchmark XML 缺口盘点存在明显误报;代表文件中的 class / benchmark 方法 `<summary>` 与 `<returns>` 已实际存在
|
||||
- 因此本轮不接受新的大范围 XML 收口波次,避免把上下文预算消耗在错误候选上
|
||||
- 本轮 accepted delegated scope 收敛为单文件 docs-only worker:
|
||||
- `GFramework.Cqrs.Benchmarks/README.md`
|
||||
- 明确 `StreamStartupBenchmarks` 现已覆盖 `MediatR`、`GFramework.Cqrs` reflection、
|
||||
`GFramework.Cqrs` generated、NuGet `Mediator` 四组 initialization / cold-start 对照
|
||||
- 补充 `RequestStartupBenchmarks` 与 `NotificationStartupBenchmarks` 的
|
||||
`GFramework.Cqrs` 路径是“单 handler 最小宿主 + 手工注册”的 startup / cold-start 模型,不外推到程序集扫描、
|
||||
完整注册协调器、fan-out 或发布策略变体
|
||||
- 当前决定在该 docs-only 收口后停在自然边界:
|
||||
- 本轮主线程将 `RequestLifetimeBenchmarks` 的 request lifetime 矩阵扩展为 baseline、`GFramework.Cqrs`、NuGet `Mediator` 与 `MediatR` 四组对照:
|
||||
- `BenchmarkRequest` 与 `BenchmarkRequestHandler` 增补 `Mediator` 契约实现
|
||||
- `Mediator` 宿主按 `Singleton / Scoped / Transient` 三种编译期常量分支生成,满足 source generator 的配置约束
|
||||
- `Scoped` 路径通过显式 `CreateScope()` 解析 generated `Mediator.Mediator`,保持与现有 request scoped 对照相同的作用域边界
|
||||
- 本轮同时收口两处 benchmark XML 文档漂移:
|
||||
- `RequestBenchmarks` 的 handler 说明补齐 NuGet `Mediator` 契约事实
|
||||
- `NotificationBenchmarks` 的类说明与 handler 说明补齐 NuGet `Mediator` 对照事实
|
||||
- 当前决定在该 parity + docs 收口后停在自然边界:
|
||||
- branch-size 仍低于 `50 files`
|
||||
- 但下一批低风险候选已不再清晰;继续开波次的收益低于评审与上下文成本
|
||||
- tests 侧此前已补齐并提交:
|
||||
@ -50,6 +50,9 @@ CQRS 迁移与收敛。
|
||||
- 当前分支:`feat/cqrs-optimization`
|
||||
- 当前 PR:`PR #349(已合并;当前分支暂无新的公开 PR)`
|
||||
- 当前写面:
|
||||
- `GFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs`
|
||||
- `GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs`
|
||||
- `GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs`
|
||||
- `GFramework.Cqrs.Benchmarks/README.md`
|
||||
- `ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md`
|
||||
- `ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
|
||||
@ -57,7 +60,7 @@ CQRS 迁移与收敛。
|
||||
- `origin/main @ 2b2bec65 (2026-05-12 11:49:39 +0800)`
|
||||
- 当前已提交 branch diff:`14 files`
|
||||
- 当前分支比 `origin/main` 多 `5` 个提交:`f346110a`、`a016e3d4`、`ab422b05`、`555c7c07`、`c32a1ec4`
|
||||
- 当前未提交面由 benchmark README 的 startup 边界同步与 `ai-plan` 恢复点更新构成
|
||||
- 当前工作面已收口为 request lifetime parity、两处 benchmark XML 文档修正与对应 `README` / `ai-plan` 同步
|
||||
- 本轮提交:
|
||||
- `f346110a` `feat(cqrs-benchmarks): 补齐 stream startup 的 Mediator 对照路径`
|
||||
- `ab422b05` `docs(cqrs-benchmarks): 补齐 request benchmark 返回值注释`
|
||||
@ -67,28 +70,28 @@ CQRS 迁移与收敛。
|
||||
## 当前风险
|
||||
|
||||
- `StreamStartupBenchmarks` 的 `Mediator` parity 目前只做了编译验证,尚未单独执行 benchmark 作业确认 startup 矩阵运行结果。
|
||||
- `StreamLifetimeBenchmarks` 仍缺 `Mediator` parity;该项涉及 `BenchmarkHostFactory` 与 compile-time lifetime 形状,不再是本轮低风险切片。
|
||||
- `StreamLifetimeBenchmarks` 仍缺 `Mediator` parity;虽然 `RequestLifetimeBenchmarks` 已证明 `Mediator` 的 compile-time lifetime 可通过常量分支接入,但 stream 侧仍需要额外处理 `IAsyncEnumerable<T>` 与作用域覆盖整个枚举周期的组合边界。
|
||||
- benchmark XML 盘点若再次依赖粗糙脚本或只读 inventory,仍有把已存在文档误记为缺口的风险;后续若再开 XML 波次,必须先用主线程抽样核对代表文件。
|
||||
- 本轮已在 README 精度同步后主动停批次;若后续恢复,优先先做 `StreamStartupBenchmarks` smoke run 或更明确的 parity / docs 候选,而不是继续机械扩张 XML 批次。
|
||||
- 本轮已在 request lifetime parity 与文档漂移收口后主动停批次;若后续恢复,优先先做 `StreamStartupBenchmarks` smoke run 或更明确的 parity / docs 候选,而不是继续机械扩张 XML 批次。
|
||||
|
||||
## 最近权威验证
|
||||
|
||||
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
|
||||
- 结果:通过,`0 warning / 0 error`
|
||||
- 备注:确认 `RequestLifetimeBenchmarks` 的 NuGet `Mediator` lifetime parity 可在当前生成器约束下编译通过
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- `$gframework-pr-review`
|
||||
- 结果:`PR #349` 已关闭;latest-head review open thread 经本地核对仅剩 `StreamingBenchmarks.Stream_MediatR()` 的 XML 文档缺口仍成立
|
||||
- `git --git-dir=/mnt/f/gewuyou/System/Documents/WorkSpace/GameDev/GFramework/.git/worktrees/GFramework-cqrs --work-tree=/mnt/f/gewuyou/System/Documents/WorkSpace/GameDev/GFramework-WorkTree/GFramework-cqrs diff -- GFramework.Cqrs.Benchmarks/README.md`
|
||||
- `git --git-dir=/mnt/f/gewuyou/System/Documents/WorkSpace/GameDev/GFramework/.git/worktrees/GFramework-cqrs --work-tree=/mnt/f/gewuyou/System/Documents/WorkSpace/GameDev/GFramework-WorkTree/GFramework-cqrs diff -- GFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs`
|
||||
- 结果:通过
|
||||
- 备注:确认本轮 worker 仅修改 README 的 startup coverage / 边界文案
|
||||
- 备注:确认本轮代码面收敛在 request lifetime parity 与两处 XML 文档漂移修正
|
||||
|
||||
## 下一推荐步骤
|
||||
|
||||
1. 串行运行 `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`、`python3 scripts/license-header.py --check --paths ...` 与 `git diff --check`,作为本轮 docs-only 收尾的权威验证。
|
||||
2. 提交当前 README 与 `ai-plan` 更新,回到干净工作树。
|
||||
3. 若后续继续 benchmark 波次,优先单独执行 `StreamStartupBenchmarks` 的最小 smoke run,验证新加 `Mediator` startup 路径可运行。
|
||||
4. 若后续再开文档批次,先用主线程核对代表文件,再决定是否存在真实 XML 缺口;不要直接沿用误报 inventory 扩批。
|
||||
1. 若后续继续 benchmark 波次,优先单独执行 `StreamStartupBenchmarks` 的最小 smoke run,验证新加 `Mediator` startup 路径可运行。
|
||||
2. 若后续评估 `StreamLifetimeBenchmarks` 的 `Mediator` parity,先复用本轮 request lifetime 的“编译期常量 lifetime 分支”经验,再判断是否值得引入新的 scoped stream helper。
|
||||
3. 若后续再开 XML / docs 批次,先由主线程逐文件核对代表样本,不要直接沿用误报 inventory 扩批。
|
||||
|
||||
## 活跃文档
|
||||
|
||||
|
||||
@ -7,6 +7,43 @@ SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
## 2026-05-12
|
||||
|
||||
### 阶段:request lifetime 的 Mediator parity 与文档漂移收口(CQRS-REWRITE-RP-140)
|
||||
|
||||
- 继续按 `$gframework-batch-boot 50` 推进,基线保持为 `origin/main @ 2b2bec65 (2026-05-12 11:49:39 +0800)`。
|
||||
- 本轮启动时重新测得当前已提交 branch diff 仍为 `14 files / 324 lines`,远低于 `50 files` 阈值;停止与否继续由 context-budget / reviewability 主导。
|
||||
- 主线程结合两个 explorer 子代理的只读盘点后,接受以下结论:
|
||||
- 不再继续按 benchmark XML `<returns>` inventory 机械扩批;粗糙脚本会把“注释位于 `[Benchmark]` 之前”的现有文档误判为缺口
|
||||
- `RequestLifetimeBenchmarks` 的 NuGet `Mediator` lifetime parity 是当前仍然真实、且能保持 reviewable 的实现候选
|
||||
- `NotificationBenchmarks.cs` 与 `RequestBenchmarks.cs` 仍有两处低风险 XML 文档漂移,均只涉及 NuGet `Mediator` 事实同步
|
||||
- 本轮主线程实施:
|
||||
- `RequestLifetimeBenchmarks.cs`
|
||||
- 新增 `GeneratedMediator` 宿主字段、`SendRequest_Mediator()` benchmark 方法与 scoped `Mediator` request helper
|
||||
- 将 `BenchmarkRequest` / `BenchmarkRequestHandler` 扩为同时实现 `Mediator` 契约
|
||||
- 为 `Mediator` 宿主改用 `Singleton / Scoped / Transient` 三个编译期常量分支,规避 `MSG0007` 对运行时 lifetime 赋值的生成器限制
|
||||
- `RequestBenchmarks.cs`
|
||||
- 将 handler XML 文档说明补齐为同时实现 `GFramework.CQRS`、NuGet `Mediator` 与 `MediatR`
|
||||
- `NotificationBenchmarks.cs`
|
||||
- 将类说明与 handler XML 文档说明补齐为同时覆盖 `GFramework.CQRS`、NuGet `Mediator` 与 `MediatR`
|
||||
- `GFramework.Cqrs.Benchmarks/README.md`
|
||||
- 将 `RequestLifetimeBenchmarks` 的 coverage 更新为包含 NuGet `Mediator` source-generated concrete path
|
||||
- 删除“当前没有 request 生命周期下的 NuGet `Mediator` compile-time lifetime 矩阵”这一已过时缺口
|
||||
- 验证里程碑:
|
||||
- 第一次 `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
|
||||
- 结果:失败
|
||||
- 原因:`RequestLifetimeBenchmarks.cs` 中基于运行时变量写入 `MediatorOptions.ServiceLifetime`,触发 `MSG0007`
|
||||
- 主线程修正:
|
||||
- 将 `CreateMediatorServiceProvider(HandlerLifetime lifetime)` 收口为 3 个常量分支工厂:
|
||||
`CreateSingletonMediatorServiceProvider()`、`CreateScopedMediatorServiceProvider()`、`CreateTransientMediatorServiceProvider()`
|
||||
- 第二次 `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
|
||||
- 结果:通过,`0 warning / 0 error`
|
||||
- 当前 stop decision:
|
||||
- 不继续开启新的实现波次
|
||||
- 原因不是 branch-size 阈值耗尽;当前分支仍只有 `14 files`
|
||||
- 停止原因是本轮已经完成一条真实 parity 收口和两处文档漂移修正,继续扩到 `StreamLifetimeBenchmarks` 会显著提高作用域与 review 成本
|
||||
- 当前下一步:
|
||||
- 主线程补跑 `python3 scripts/license-header.py --check --paths ...` 与 `git diff --check`
|
||||
- 更新 active tracking / trace 后提交当前 benchmark 代码、README 与 `ai-plan`
|
||||
|
||||
### 阶段:README startup coverage 精度同步并停在自然边界(CQRS-REWRITE-RP-139)
|
||||
|
||||
- 继续按 `$gframework-batch-boot 50` 推进,基线保持为 `origin/main @ 2b2bec65 (2026-05-12 11:49:39 +0800)`。
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user