mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-09 01:54:30 +08:00
fix(cqrs): 收口PR审查遗留问题
- 修复 benchmark 宿主误激活同程序集其他 generated registry 的接线路径,收窄服务索引与 descriptor 基线 - 恢复 CqrsDispatcher.SendAsync 的 faulted ValueTask 失败语义,并补充相关回归测试 - 补充 legacy runtime alias 的防守式类型检查、stream lifetime 注释与 cqrs-rewrite 恢复文档验证记录
This commit is contained in:
parent
39ac61c095
commit
9bd8c34693
@ -147,7 +147,7 @@ When shorthand is used:
|
||||
6. After each completed batch:
|
||||
- integrate or verify the result
|
||||
- rerun the required validation
|
||||
- recompute the primary stop-condition metric
|
||||
- recompute the primary stop-condition metric
|
||||
- reassess whether one more batch would likely push the agent near or beyond roughly 80% context usage
|
||||
- decide immediately whether to continue or stop
|
||||
7. Do not require the user to manually trigger every round unless:
|
||||
|
||||
@ -6,6 +6,7 @@ using System.Linq;
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
using GFramework.Core.Ioc;
|
||||
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||
using GFramework.Cqrs.Internal;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using LegacyICqrsRuntime = GFramework.Core.Abstractions.Cqrs.ICqrsRuntime;
|
||||
@ -58,11 +59,11 @@ internal static class BenchmarkHostFactory
|
||||
var notificationPublisher = container.Get<GFramework.Cqrs.Notification.INotificationPublisher>();
|
||||
var runtime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(container, runtimeLogger, notificationPublisher);
|
||||
container.Register(runtime);
|
||||
container.Register<LegacyICqrsRuntime>((LegacyICqrsRuntime)runtime);
|
||||
RegisterLegacyRuntimeAlias(container, runtime);
|
||||
}
|
||||
else if (container.Get<LegacyICqrsRuntime>() is null)
|
||||
{
|
||||
container.Register<LegacyICqrsRuntime>((LegacyICqrsRuntime)container.GetRequired<ICqrsRuntime>());
|
||||
RegisterLegacyRuntimeAlias(container, container.GetRequired<ICqrsRuntime>());
|
||||
}
|
||||
|
||||
if (container.Get<ICqrsHandlerRegistrar>() is null)
|
||||
@ -81,6 +82,43 @@ internal static class BenchmarkHostFactory
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 只激活当前 benchmark 场景明确拥有的 generated registry,避免同一程序集里的其他 benchmark registry
|
||||
/// 扩大冻结后服务索引与 dispatcher descriptor 基线。
|
||||
/// </summary>
|
||||
/// <typeparam name="TRegistry">当前 benchmark 需要接入的 generated registry 类型。</typeparam>
|
||||
/// <param name="container">承载 generated registry 注册结果的 GFramework benchmark 容器。</param>
|
||||
internal static void RegisterGeneratedBenchmarkRegistry<TRegistry>(MicrosoftDiContainer container)
|
||||
where TRegistry : class, GFramework.Cqrs.ICqrsHandlerRegistry
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(container);
|
||||
|
||||
var registrarLogger = LoggerFactoryResolver.Provider.CreateLogger("DefaultCqrsHandlerRegistrar");
|
||||
CqrsHandlerRegistrar.RegisterGeneratedRegistry(container, typeof(TRegistry), registrarLogger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为旧命名空间下的 CQRS runtime 契约注册兼容别名。
|
||||
/// </summary>
|
||||
/// <param name="container">承载 runtime 别名的 benchmark 容器。</param>
|
||||
/// <param name="runtime">当前正式 CQRS runtime 实例。</param>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// <paramref name="runtime" /> 未同时实现 legacy CQRS runtime 契约。
|
||||
/// </exception>
|
||||
private static void RegisterLegacyRuntimeAlias(MicrosoftDiContainer container, ICqrsRuntime runtime)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(container);
|
||||
ArgumentNullException.ThrowIfNull(runtime);
|
||||
|
||||
if (runtime is not LegacyICqrsRuntime legacyRuntime)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"The registered {typeof(ICqrsRuntime).FullName} must also implement {typeof(LegacyICqrsRuntime).FullName}. Actual runtime type: {runtime.GetType().FullName}.");
|
||||
}
|
||||
|
||||
container.Register<LegacyICqrsRuntime>(legacyRuntime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建只承载当前 benchmark handler 集合的最小 MediatR 宿主。
|
||||
/// </summary>
|
||||
|
||||
@ -66,7 +66,7 @@ public class RequestBenchmarks
|
||||
_baselineHandler = new BenchmarkRequestHandler();
|
||||
_container = BenchmarkHostFactory.CreateFrozenGFrameworkContainer(container =>
|
||||
{
|
||||
container.RegisterCqrsHandlersFromAssembly(typeof(RequestBenchmarks).Assembly);
|
||||
BenchmarkHostFactory.RegisterGeneratedBenchmarkRegistry<GeneratedDefaultRequestBenchmarkRegistry>(container);
|
||||
});
|
||||
_runtime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(
|
||||
_container,
|
||||
|
||||
@ -83,7 +83,7 @@ public class RequestInvokerBenchmarks
|
||||
|
||||
_generatedContainer = BenchmarkHostFactory.CreateFrozenGFrameworkContainer(container =>
|
||||
{
|
||||
container.RegisterCqrsHandlersFromAssembly(typeof(RequestInvokerBenchmarks).Assembly);
|
||||
BenchmarkHostFactory.RegisterGeneratedBenchmarkRegistry<GeneratedRequestInvokerBenchmarkRegistry>(container);
|
||||
});
|
||||
_generatedRuntime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(
|
||||
_generatedContainer,
|
||||
|
||||
@ -69,7 +69,7 @@ public class RequestPipelineBenchmarks
|
||||
_baselineHandler = new BenchmarkRequestHandler();
|
||||
_container = BenchmarkHostFactory.CreateFrozenGFrameworkContainer(container =>
|
||||
{
|
||||
container.RegisterCqrsHandlersFromAssembly(typeof(RequestPipelineBenchmarks).Assembly);
|
||||
BenchmarkHostFactory.RegisterGeneratedBenchmarkRegistry<GeneratedRequestPipelineBenchmarkRegistry>(container);
|
||||
RegisterGFrameworkPipelineBehaviors(container, PipelineCount);
|
||||
});
|
||||
_runtime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(
|
||||
|
||||
@ -83,7 +83,7 @@ public class StreamInvokerBenchmarks
|
||||
|
||||
_generatedContainer = BenchmarkHostFactory.CreateFrozenGFrameworkContainer(container =>
|
||||
{
|
||||
container.RegisterCqrsHandlersFromAssembly(typeof(StreamInvokerBenchmarks).Assembly);
|
||||
BenchmarkHostFactory.RegisterGeneratedBenchmarkRegistry<GeneratedStreamInvokerBenchmarkRegistry>(container);
|
||||
});
|
||||
_generatedRuntime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(
|
||||
_generatedContainer,
|
||||
|
||||
@ -93,9 +93,11 @@ public class StreamLifetimeBenchmarks
|
||||
|
||||
_container = BenchmarkHostFactory.CreateFrozenGFrameworkContainer(container =>
|
||||
{
|
||||
container.RegisterCqrsHandlersFromAssembly(typeof(StreamLifetimeBenchmarks).Assembly);
|
||||
BenchmarkHostFactory.RegisterGeneratedBenchmarkRegistry<GeneratedStreamLifetimeBenchmarkRegistry>(container);
|
||||
RegisterGFrameworkHandler(container, Lifetime);
|
||||
});
|
||||
// 容器内已提前保留默认 runtime 以支撑 generated registry 接线;
|
||||
// 这里额外创建带生命周期后缀的 runtime,只是为了区分不同 benchmark 矩阵的 dispatcher 日志。
|
||||
_runtime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(
|
||||
_container,
|
||||
LoggerFactoryResolver.Provider.CreateLogger(nameof(StreamLifetimeBenchmarks) + "." + Lifetime));
|
||||
|
||||
@ -67,7 +67,7 @@ public class StreamingBenchmarks
|
||||
_baselineHandler = new BenchmarkStreamHandler();
|
||||
_container = BenchmarkHostFactory.CreateFrozenGFrameworkContainer(container =>
|
||||
{
|
||||
container.RegisterCqrsHandlersFromAssembly(typeof(StreamingBenchmarks).Assembly);
|
||||
BenchmarkHostFactory.RegisterGeneratedBenchmarkRegistry<GeneratedDefaultStreamingBenchmarkRegistry>(container);
|
||||
});
|
||||
_runtime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(
|
||||
_container,
|
||||
|
||||
@ -43,6 +43,57 @@ internal sealed class CqrsDispatcherContextValidationTests
|
||||
Throws.InvalidOperationException.With.Message.Contains("does not implement IArchitectureContext"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证 request 上下文校验失败时,<see cref="GFramework.Cqrs.Abstractions.Cqrs.ICqrsRuntime.SendAsync{TResponse}" />
|
||||
/// 不会在调用点同步抛出,而是返回一个 faulted <see cref="ValueTask{TResult}" /> 保持既有异步失败语义。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SendAsync_Should_Return_Faulted_ValueTask_When_Context_Preparation_Fails()
|
||||
{
|
||||
var runtime = CreateRuntime(
|
||||
container =>
|
||||
{
|
||||
container
|
||||
.Setup(currentContainer => currentContainer.Get(typeof(IRequestHandler<ContextAwareRequest, int>)))
|
||||
.Returns(new ContextAwareRequestHandler());
|
||||
container
|
||||
.Setup(currentContainer => currentContainer.HasRegistration(typeof(IPipelineBehavior<ContextAwareRequest, int>)))
|
||||
.Returns(false);
|
||||
});
|
||||
|
||||
ValueTask<int> dispatch = default;
|
||||
Assert.That(
|
||||
() => { dispatch = runtime.SendAsync(new FakeCqrsContext(), new ContextAwareRequest()); },
|
||||
Throws.Nothing);
|
||||
Assert.That(
|
||||
async () => await dispatch.ConfigureAwait(false),
|
||||
Throws.InvalidOperationException.With.Message.Contains("does not implement IArchitectureContext"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证 request handler 缺失时,dispatcher 仍返回 faulted <see cref="ValueTask{TResult}" />,
|
||||
/// 而不是在调用点同步抛出异常。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SendAsync_Should_Return_Faulted_ValueTask_When_Handler_Is_Missing()
|
||||
{
|
||||
var runtime = CreateRuntime(
|
||||
container =>
|
||||
{
|
||||
container
|
||||
.Setup(currentContainer => currentContainer.Get(typeof(IRequestHandler<ContextAwareRequest, int>)))
|
||||
.Returns((object?)null);
|
||||
});
|
||||
|
||||
ValueTask<int> dispatch = default;
|
||||
Assert.That(
|
||||
() => { dispatch = runtime.SendAsync(new FakeCqrsContext(), new ContextAwareRequest()); },
|
||||
Throws.Nothing);
|
||||
Assert.That(
|
||||
async () => await dispatch.ConfigureAwait(false),
|
||||
Throws.InvalidOperationException.With.Message.Contains("No CQRS request handler registered"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证当 notification handler 需要上下文注入、但当前 CQRS 上下文不实现 <see cref="GFramework.Core.Abstractions.Architectures.IArchitectureContext" /> 时,
|
||||
/// dispatcher 会在发布前显式失败。
|
||||
|
||||
@ -7,6 +7,7 @@ using GFramework.Core.Architectures;
|
||||
using GFramework.Core.Ioc;
|
||||
using GFramework.Core.Logging;
|
||||
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||
using GFramework.Cqrs.Internal;
|
||||
|
||||
namespace GFramework.Cqrs.Tests.Cqrs;
|
||||
|
||||
@ -99,6 +100,32 @@ internal sealed class CqrsGeneratedRequestInvokerProviderTests
|
||||
Is.EqualTo([typeof(GeneratedStreamInvokerProviderRegistry)]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证 direct generated-registry 激活入口只会接入指定 registry,而不会顺手把同一测试程序集里的其他 registry 一并注册。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void RegisterGeneratedRegistry_Should_Register_Only_The_Selected_Provider()
|
||||
{
|
||||
var container = new MicrosoftDiContainer();
|
||||
var logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(CqrsGeneratedRequestInvokerProviderTests));
|
||||
|
||||
CqrsHandlerRegistrar.RegisterGeneratedRegistry(
|
||||
container,
|
||||
typeof(GeneratedRequestInvokerProviderRegistry),
|
||||
logger);
|
||||
|
||||
var requestProviders = container.GetAll<ICqrsRequestInvokerProvider>();
|
||||
var streamProviders = container.GetAll<ICqrsStreamInvokerProvider>();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(
|
||||
requestProviders.Select(static provider => provider.GetType()),
|
||||
Is.EqualTo([typeof(GeneratedRequestInvokerProviderRegistry)]));
|
||||
Assert.That(streamProviders, Is.Empty);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证当实现类型隐藏、但 stream handler interface 仍可直接表达时,
|
||||
/// registrar 仍会把 generated stream invoker provider 注册到容器中。
|
||||
|
||||
@ -110,30 +110,38 @@ internal sealed class CqrsDispatcher(
|
||||
IRequest<TResponse> request,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
|
||||
var requestType = request.GetType();
|
||||
var dispatchBinding = GetRequestDispatchBinding<TResponse>(requestType);
|
||||
var handler = container.Get(dispatchBinding.HandlerType)
|
||||
?? throw new InvalidOperationException(
|
||||
$"No CQRS request handler registered for {requestType.FullName}.");
|
||||
|
||||
PrepareHandler(handler, context);
|
||||
if (!container.HasRegistration(dispatchBinding.BehaviorType))
|
||||
try
|
||||
{
|
||||
return dispatchBinding.RequestInvoker(handler, request, cancellationToken);
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
|
||||
var requestType = request.GetType();
|
||||
var dispatchBinding = GetRequestDispatchBinding<TResponse>(requestType);
|
||||
var handler = container.Get(dispatchBinding.HandlerType)
|
||||
?? throw new InvalidOperationException(
|
||||
$"No CQRS request handler registered for {requestType.FullName}.");
|
||||
|
||||
PrepareHandler(handler, context);
|
||||
if (!container.HasRegistration(dispatchBinding.BehaviorType))
|
||||
{
|
||||
return dispatchBinding.RequestInvoker(handler, request, cancellationToken);
|
||||
}
|
||||
|
||||
var behaviors = container.GetAll(dispatchBinding.BehaviorType);
|
||||
|
||||
foreach (var behavior in behaviors)
|
||||
{
|
||||
PrepareHandler(behavior, context);
|
||||
}
|
||||
|
||||
return dispatchBinding.GetPipelineExecutor(behaviors.Count)
|
||||
.Invoke(handler, behaviors, request, cancellationToken);
|
||||
}
|
||||
|
||||
var behaviors = container.GetAll(dispatchBinding.BehaviorType);
|
||||
|
||||
foreach (var behavior in behaviors)
|
||||
catch (Exception exception)
|
||||
{
|
||||
PrepareHandler(behavior, context);
|
||||
// 保留旧 async 实现的 faulted-ValueTask 失败语义,同时继续复用 direct-return 的热路径。
|
||||
return ValueTask.FromException<TResponse>(exception);
|
||||
}
|
||||
|
||||
return dispatchBinding.GetPipelineExecutor(behaviors.Count)
|
||||
.Invoke(handler, behaviors, request, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -68,6 +68,36 @@ internal static class CqrsHandlerRegistrar
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 直接激活并注册单个 generated registry,避免调用方为了只接入一个 benchmark registry
|
||||
/// 而额外扫描同一程序集里的其他 registry / handler。
|
||||
/// </summary>
|
||||
/// <param name="container">承载 generated registry 注册结果的目标容器。</param>
|
||||
/// <param name="registryType">要直接激活的 generated registry 类型。</param>
|
||||
/// <param name="logger">当前注册过程使用的日志记录器。</param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="container" />、<paramref name="registryType" /> 或 <paramref name="logger" /> 为 <see langword="null" />。
|
||||
/// </exception>
|
||||
/// <exception cref="InvalidOperationException">指定 registry 类型不满足 generated registry 运行时契约。</exception>
|
||||
internal static void RegisterGeneratedRegistry(
|
||||
IIocContainer container,
|
||||
Type registryType,
|
||||
ILogger logger)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(container);
|
||||
ArgumentNullException.ThrowIfNull(registryType);
|
||||
ArgumentNullException.ThrowIfNull(logger);
|
||||
|
||||
var assemblyName = GetAssemblySortKey(registryType.Assembly);
|
||||
if (!TryCreateGeneratedRegistry(registryType, assemblyName, logger, out var registry))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Unable to activate generated CQRS handler registry {registryType.FullName} in assembly {assemblyName}.");
|
||||
}
|
||||
|
||||
RegisterGeneratedRegistries(container.GetServicesUnsafe, [registry], assemblyName, logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 优先使用程序集级源码生成注册器完成 CQRS 映射注册。
|
||||
/// </summary>
|
||||
|
||||
7
GFramework.Cqrs/Properties/AssemblyInfo.cs
Normal file
7
GFramework.Cqrs/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright (c) 2025-2026 GeWuYou
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("GFramework.Cqrs.Tests")]
|
||||
[assembly: InternalsVisibleTo("GFramework.Cqrs.Benchmarks")]
|
||||
@ -7,10 +7,11 @@ CQRS 迁移与收敛。
|
||||
|
||||
## 当前恢复点
|
||||
|
||||
- 恢复点编号:`CQRS-REWRITE-RP-108`
|
||||
- 恢复点编号:`CQRS-REWRITE-RP-109`
|
||||
- 当前阶段:`Phase 8`
|
||||
- 当前 PR 锚点:`PR #340`
|
||||
- 当前 PR 锚点:`PR #341`
|
||||
- 当前结论:
|
||||
- 当前 `RP-109` 已使用 `$gframework-pr-review` 复核 `PR #341` latest-head review:benchmark 宿主改为定向激活当前场景的 generated registry,避免同一 benchmark 程序集里的其他 registry 扩大冻结服务索引与 `HasRegistration` 基线;`BenchmarkHostFactory` 为 legacy runtime alias 注册补齐防守式类型检查与 stream lifetime 运行时注释;`CqrsDispatcher.SendAsync(...)` 在保留 direct-return 热路径的同时恢复 faulted `ValueTask` 失败语义,并补齐 generated registry 定向接线与 request fault 语义回归测试;`.agents/skills/gframework-batch-boot/SKILL.md` 的 MD005 缩进也已顺手修正
|
||||
- `GFramework.Cqrs` 已完成对外部 `Mediator` 的生产级替代,当前主线已从“是否可替代”转向“仓库内部收口与能力深化顺序”
|
||||
- `dispatch/invoker` 生成前移已扩展到 request / stream 路径,`RP-077` 已补齐 request invoker provider gate 与 stream gate 对称的 descriptor / descriptor entry runtime 合同回归
|
||||
- `RP-078` 已补齐 mixed fallback metadata 在 runtime 不允许多个 fallback attribute 实例时的单字符串 attribute 回退回归
|
||||
|
||||
@ -2,6 +2,35 @@
|
||||
|
||||
## 2026-05-08
|
||||
|
||||
### 阶段:PR #341 latest-head review 收口(CQRS-REWRITE-RP-109)
|
||||
|
||||
- 使用 `$gframework-pr-review` 抓取 `feat/cqrs-optimization` 当前公开 PR,并确认当前锚点已从 `PR #340` 更新为 `PR #341`
|
||||
- 本轮 latest-head review 结论:
|
||||
- `CodeRabbit` 仍有 `BenchmarkHostFactory.cs` 的 legacy runtime 硬转型、`StreamLifetimeBenchmarks.cs` 的注释缺口,以及 `.agents/skills/gframework-batch-boot/SKILL.md` 的 `MD005` 缩进问题
|
||||
- `Greptile` 指出的两条仍然成立:benchmark 项目里通过 `RegisterCqrsHandlersFromAssembly(typeof(...).Assembly)` 会把同程序集的其他 generated registry 一并激活,扩大 benchmark 宿主的服务索引基线;`CqrsDispatcher.SendAsync(...)` 直接去掉 `async/await` 后也把原本的 faulted-`ValueTask` 失败语义改成了同步抛出
|
||||
- 本轮主线程决策:
|
||||
- 在 `GFramework.Cqrs.Internal.CqrsHandlerRegistrar` 新增 direct generated-registry 激活入口,并通过 `InternalsVisibleTo` 暴露给 `GFramework.Cqrs.Benchmarks`,让 benchmark 宿主只激活当前场景的 generated registry
|
||||
- 把 `RequestBenchmarks`、`RequestPipelineBenchmarks`、`StreamingBenchmarks`、`StreamLifetimeBenchmarks` 以及 request/stream invoker benchmark 的 generated 宿主全部切到定向 registry 接线,避免同程序集其他 registry 扩大冻结索引和 descriptor 预热基线
|
||||
- 在 `BenchmarkHostFactory` 里用防守式类型检查注册 legacy runtime alias,并补充 stream lifetime runtime 二次创建的注释
|
||||
- 让 `CqrsDispatcher.SendAsync(...)` 通过 `ValueTask.FromException<TResponse>(...)` 恢复旧的 faulted-`ValueTask` 失败语义,同时保留成功路径的 direct-return 热路径
|
||||
- 补齐 `CqrsGeneratedRequestInvokerProviderTests` 与 `CqrsDispatcherContextValidationTests` 的 targeted 回归,并顺手修正 batch boot skill 的 markdown 缩进
|
||||
- 本轮权威验证:
|
||||
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
|
||||
- 结果:通过,`1 warning / 0 error`
|
||||
- 备注:仅出现 `MSB3026` 单次复制重试告警,随后成功产出 `net10.0` 目标;未出现编译失败或新增代码警告
|
||||
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
|
||||
- 结果:通过,`0 warning / 0 error`
|
||||
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsDispatcherContextValidationTests|FullyQualifiedName~CqrsGeneratedRequestInvokerProviderTests"`
|
||||
- 结果:通过,`24/24` passed
|
||||
- 备注:首轮并行验证时因与 build 同时运行触发 MSBuild 输出文件锁竞争;改为串行重跑同一命令后稳定通过
|
||||
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs/Properties/AssemblyInfo.cs GFramework.Cqrs/Internal/CqrsHandlerRegistrar.cs GFramework.Cqrs/Internal/CqrsDispatcher.cs GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs GFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.cs GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs GFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.cs GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs GFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.cs`
|
||||
- 结果:通过
|
||||
- 备注:仓库脚本默认内部调用未绑定 worktree 的 `git ls-files`,因此本轮按修改文件列表显式 `--paths` 校验
|
||||
- `git diff --check`
|
||||
- 结果:通过
|
||||
- 本轮下一步:
|
||||
- 运行 `GFramework.Cqrs` / `GFramework.Cqrs.Benchmarks` 的 Release build、相关 targeted tests、license header check 与 `git diff --check`
|
||||
|
||||
### 阶段:stream handler 生命周期矩阵 benchmark(CQRS-REWRITE-RP-108)
|
||||
|
||||
- 延续 `$gframework-batch-boot 50`,本轮继续使用 `origin/main` 作为 branch diff 基线,并先复核:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user