Feat/Implement CQRS runtime integration for legacy compatibility#334
Conversation
- 新增 request handler Singleton 与 Transient 生命周期 benchmark,并说明 Scoped 对照的宿主前置条件 - 更新 benchmark README,补充当前覆盖范围与后续扩展方向 - 更新 cqrs-rewrite active tracking 与 trace,记录 RP-092 验证结果和沙箱外 benchmark 权威结论
- 重构 Core 兼容命令查询入口,使 legacy SendCommand/SendQuery 通过内部 bridge request 复用统一 CQRS runtime - 新增 legacy bridge handler 与真实启动路径回归测试,验证默认架构初始化会自动接入统一 pipeline - 更新 Core 与 CQRS 文档及 cqrs-rewrite 跟踪,记录 Mediator 尚未吸收的能力差距与后续收口方向
|
Warning Rate limit exceeded
To continue reviewing without waiting, purchase usage credits in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughPR 将旧的 SendQuery/SendCommand 系列封装为多种 Legacy*DispatchRequest,并通过新增的 LegacyCqrsDispatchHelper 与可选 ICqrsRuntime 运行时将 legacy 请求路由到统一 pipeline;更新 Executors 与 ArchitectureContext 以优先通过 runtime 桥接(无法解析时回退到 legacy 执行);补入大量测试、基准与文档更新。 ChangesLegacy CQRS 运行时桥接
Sequence Diagram sequenceDiagram
participant Caller
participant Arch as ArchitectureContext
participant Helper as LegacyCqrsDispatchHelper
participant Runtime as ICqrsRuntime
Caller->>Arch: SendQuery/SendCommand(legacy)
Arch->>Helper: SendRequest / SendSynchronously(Legacy*DispatchRequest)
Helper->>Runtime: SendAsync(dispatchRequest)
Runtime->>Handler: pipeline -> Handle(request)
Handler-->>Runtime: 返回 boxed 结果
Arch-->>Caller: 转换并返回
估计审查工作量🎯 4 (Complex) | ⏱️ ~50 分钟 可能相关的 PR
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
|
Summary
Test ResultsDetails
Insights
build-and-test: Run #1077
🎉 All tests passed!Slowest Tests
± Comparison with run #1063 at 984c144 | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 28 runs. Github Test Reporter by CTRF 💚 |
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|
| dotnet-format | yes | 1 | no | 4.97s | ||
| ✅ REPOSITORY | gitleaks | yes | no | no | 8.28s | |
| ✅ REPOSITORY | trufflehog | yes | no | no | 7.08s |
Detailed Issues
⚠️ CSHARP / dotnet-format - 1 error
Welcome to .NET 9.0!
---------------------
SDK Version: 9.0.114
----------------
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate, run 'dotnet dev-certs https --trust'
Learn about HTTPS: https://aka.ms/dotnet-https
----------------
Write your first app: https://aka.ms/dotnet-hello-world
Find out what's new: https://aka.ms/dotnet-whats-new
Explore documentation: https://aka.ms/dotnet-docs
Report issues and find source on GitHub: https://github.com/dotnet/core
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli
--------------------------------------------------------------------------------------
Unhandled exception: System.Exception: Restore operation failed.
at Microsoft.CodeAnalysis.Tools.CodeFormatter.OpenMSBuildWorkspaceAsync(String solutionOrProjectPath, WorkspaceType workspaceType, Boolean noRestore, Boolean requiresSemantics, String binaryLogPath, Boolean logWorkspaceWarnings, ILogger logger, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Tools.CodeFormatter.FormatWorkspaceAsync(FormatOptions formatOptions, ILogger logger, CancellationToken cancellationToken, String binaryLogPath)
at Microsoft.CodeAnalysis.Tools.FormatCommandCommon.FormatAsync(FormatOptions formatOptions, ILogger`1 logger, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Tools.Commands.RootFormatCommand.FormatCommandDefaultHandler.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
at System.CommandLine.Invocation.InvocationPipeline.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
See detailed reports in MegaLinter artifacts
Set VALIDATE_ALL_CODEBASE: true in mega-linter.yml to validate all sources, not only the diff

Show us your support by starring ⭐ the repository
|
| Filename | Overview |
|---|---|
| GFramework.Core/Cqrs/LegacyCqrsDispatchHelper.cs | Core bridge helper: TryResolveDispatchContext narrows exception catch to two hardcoded message strings (fragile); SendSynchronously uses Task.Run to avoid sync-context deadlocks correctly. |
| GFramework.Core/Command/CommandExecutor.cs | Adds optional ICqrsRuntime bridge path to all four send overloads; sync overloads go through Task.Run-backed SendSynchronously, async overloads pass the ValueTask directly. |
| GFramework.Core/Architectures/ArchitectureContext.cs | Routes all legacy sync/async command and query entry points through LegacyCqrsDispatchHelper; SendRequest now uses Task.Run-backed sync wait instead of direct GetAwaiter().GetResult(). |
| GFramework.Core/Cqrs/LegacyCqrsDispatchHandlerBase.cs | Shared base for bridge handlers; PrepareTarget injects architecture context into IContextAware targets and throws clearly when context is unavailable. |
| GFramework.Core/Services/Modules/CommandExecutorModule.cs | Now calls container.GetRequired<ICqrsRuntime>() at register time; hard dependency on CqrsRuntimeModule is documented in XML remarks but there is no runtime guard if the runtime is absent. |
| GFramework.Core.Tests/Command/RecordingCqrsRuntime.cs | Thorough test double for ICqrsRuntime that mirrors real bridge-handler semantics including context injection and cancellation. |
| GFramework.Core.Tests/Architectures/LegacyBridgePipelineTracker.cs | Static shared counter with Volatile/Interlocked for thread safety; guarded by [NonParallelizable] and Reset() calls but remains process-wide shared state. |
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
GFramework.Core/Cqrs/LegacyCqrsDispatchHelper.cs:65-77
**Fragile string-literal guards in `IsMissingContextException`**
The two hardcoded message strings are the sole mechanism for distinguishing "no context available" from any other `InvalidOperationException`. Both strings currently match the messages thrown by `GameContext.GetFirstArchitectureContext()` and `ContextAwareStateBase.GetContext()`, but they are duplicated across this helper and the test's `MissingContextLegacyCommand` stub with no compile-time link to the originating throw sites. If either source message is ever edited during a refactor, `IsMissingContextException` will silently return `false` for genuine "no context" cases, turning a safe fallback into a propagated exception that breaks all non-context-aware bridge callers.
Consider extracting the sentinel strings to `internal static readonly` constants defined alongside the places that throw them, or introducing a dedicated `MissingArchitectureContextException` that `GetFirstArchitectureContext()` and the state bases throw instead of `InvalidOperationException`.
```suggestion
// These message strings MUST stay in sync with:
// • GFramework.Core/State/ContextAwareStateBase.cs – _context ?? throw new IOE(MissingContextMessage)
// • GFramework.Core/State/AsyncContextAwareStateBase.cs – _context ?? throw new IOE(MissingContextMessage)
// • GFramework.Core/Architectures/GameContext.cs – throw new IOE(NoActiveContextMessage)
//
// TODO: replace these literals with shared constants (or a dedicated MissingArchitectureContextException)
// so a future rename is caught at compile time.
internal const string MissingContextMessage =
"Architecture context has not been set. Call SetContext before accessing the context.";
internal const string NoActiveContextMessage =
"No active architecture context is currently bound.";
private static bool IsMissingContextException(InvalidOperationException exception)
{
ArgumentNullException.ThrowIfNull(exception);
return string.Equals(exception.Message, MissingContextMessage, StringComparison.Ordinal)
|| string.Equals(exception.Message, NoActiveContextMessage, StringComparison.Ordinal);
}
```
Reviews (6): Last reviewed commit: "fix(core): 收窄 legacy bridge 上下文回退异常边界" | Re-trigger Greptile
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
GFramework.Core/Services/Modules/AsyncQueryExecutorModule.cs (1)
33-40: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Register的 XML 注释建议补齐异常与运行时依赖约束这里已经引入显式 null 校验和
ICqrsRuntime解析依赖,建议在Register的 XML 文档中补充<exception>与<remarks>,明确失败路径与前置注册条件。📝 建议补充
/// <summary> /// 注册异步查询执行器到依赖注入容器。 /// 创建异步查询执行器实例并将其注册为多例服务。 /// </summary> /// <param name="container">依赖注入容器实例。</param> +/// <exception cref="ArgumentNullException">当 <paramref name="container"/> 为 null 时抛出。</exception> +/// <exception cref="Exception">当容器无法解析 <see cref="ICqrsRuntime"/> 时,抛出容器实现定义的异常。</exception> +/// <remarks> +/// 该模块依赖容器中已注册 <see cref="ICqrsRuntime"/>。 +/// </remarks> public void Register(IIocContainer container)As per coding guidelines,
**/*.cs: XML documentation MUST use<summary>,<param>,<returns>,<exception>, and<remarks>where applicable, and explain intent, contract, and usage constraints.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Services/Modules/AsyncQueryExecutorModule.cs` around lines 33 - 40, 为 Register 方法补全 XML 文档:在现有 <summary> 和 <param> 之外加入 <exception> 标记说明当 container 为 null 时会抛出 ArgumentNullException,以及当无法解析 ICqrsRuntime 时可能抛出的 InvalidOperationException(或容器特定的解析异常);在 <remarks> 中说明该方法会从容器解析 ICqrsRuntime 并以多例/瞬态形式注册 AsyncQueryExecutor,强调调用方必须先在容器中注册 ICqrsRuntime(或等效运行时)以避免解析失败,并注明注册语义(多例/Transient)。GFramework.Core/Services/Modules/CommandExecutorModule.cs (1)
33-40: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Register建议补充异常与依赖约束的 XML 注释这里已引入
ThrowIfNull和container.Get<ICqrsRuntime>()的前置条件,建议在文档里明确,提升 API 合同可读性与可维护性。As per coding guidelines,
**/*.cs: XML documentation MUST use<summary>,<param>,<returns>,<exception>, and<remarks>where applicable, and explain intent, contract, and usage constraints.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Services/Modules/CommandExecutorModule.cs` around lines 33 - 40, 为 Register(IIocContainer) 方法补充完整 XML 注释,说明方法行为、参数约束和可能抛出的异常:在 <summary> 里描述“将 CommandExecutor 注册为多例服务”;在 <param name="container"> 中说明必须非空且实现 IIocContainer;新增 <exception cref="ArgumentNullException"> 说明当 container 为 null 时会抛出(因内部使用 ArgumentNullException.ThrowIfNull);新增 <remarks> 或 <returns>(如适用)说明内部会通过 container.Get<ICqrsRuntime>() 获取依赖并因此要求容器能解析 ICqrsRuntime。确保引用的方法/类型名为 Register, IIocContainer, CommandExecutor, ArgumentNullException.ThrowIfNull, container.Get<ICqrsRuntime>() 以便在文档中清晰指出调用契约。GFramework.Core/Services/Modules/QueryExecutorModule.cs (1)
33-40: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win建议为
Register增加<exception>/<remarks>,显式声明ICqrsRuntime依赖这次改动引入了运行时解析依赖和明确异常路径,建议把方法契约写进 XML 注释,避免调用方只看签名时遗漏前置条件。
As per coding guidelines,
**/*.cs: XML documentation MUST use<summary>,<param>,<returns>,<exception>, and<remarks>where applicable, and explain intent, contract, and usage constraints.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Services/Modules/QueryExecutorModule.cs` around lines 33 - 40, Update the XML documentation for QueryExecutorModule.Register to include an <exception> that documents ArgumentNullException thrown when the container is null and to explicitly state that this method resolves an ICqrsRuntime from the container; in the <remarks> describe the precondition that an ICqrsRuntime implementation must be registered in the IIocContainer before calling Register (since the method constructs new QueryExecutor(container.Get<ICqrsRuntime>()) and registers it via container.RegisterPlurality). Ensure <summary> and <param name="container"> remain, and mention the behavior of creating and registering a QueryExecutor instance.GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs (1)
35-40:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
[TearDown]未重置LegacyBridgePipelineTracker。现有
TearDown已正确重置TrackingPipelineBehavior,但遗漏了LegacyBridgePipelineTracker。测试完成后残留的计数可能影响后续测试的断言。🔧 建议修复
public void TearDown() { GameContext.Clear(); TrackingPipelineBehavior<ModuleBehaviorRequest, string>.InvocationCount = 0; + LegacyBridgePipelineTracker.Reset(); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs` around lines 35 - 40, TearDown currently clears GameContext and resets TrackingPipelineBehavior<ModuleBehaviorRequest, string>.InvocationCount but forgets to reset LegacyBridgePipelineTracker; update the TearDown method to also reset the LegacyBridgePipelineTracker's count/state (the static counter or relevant reset method on LegacyBridgePipelineTracker) so tests don't leak state between runs.
🧹 Nitpick comments (10)
GFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequest.cs (1)
8-11: ⚡ Quick win补充主构造函数参数的
<param>及ExecuteAsync的<returns>XML 文档与
LegacyAsyncCommandResultDispatchRequest存在相同的文档缺失问题:类级别 XML 注释未包含target和executeAsync的<param>标签,ExecuteAsync()也缺少<returns>说明。✏️ 建议修复
/// <summary> /// 包装 legacy 异步查询,使其能够通过自有 CQRS runtime 调度。 /// </summary> +/// <param name="target">bridge request 所代理的 legacy 目标对象,不可为 <see langword="null"/>。</param> +/// <param name="executeAsync">封装 legacy 查询执行逻辑的异步委托,不可为 <see langword="null"/>。</param> internal sealed class LegacyAsyncQueryDispatchRequest(object target, Func<Task<object?>> executeAsync)/// <summary> /// 异步执行底层 legacy 查询并返回装箱后的结果。 /// </summary> + /// <returns>legacy 查询执行完成后装箱的返回值;若查询无返回值则为 <see langword="null"/>。</returns> public Task<object?> ExecuteAsync() => _executeAsync();As per coding guidelines: "XML documentation MUST use
<summary>,<param>,<returns>,<exception>, and<remarks>where applicable".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequest.cs` around lines 8 - 11, 为 LegacyAsyncQueryDispatchRequest 的主构造函数补充 XML 文档中的 <param> 标签,分别说明 target(被包装的目标对象或处理者)和 executeAsync(执行查询的委托,返回 Task<object?>)的含义;同时在 ExecuteAsync 方法的 XML 注释中添加 <returns>,明确返回值是 Task<object?>(表示异步查询结果或 null);参照 LegacyAsyncCommandResultDispatchRequest 的注释样式确保使用 <summary>、<param> 和 <returns> 并在注释中使用类名 LegacyAsyncQueryDispatchRequest 和方法名 ExecuteAsync 作为定位参考。GFramework.Core/Cqrs/LegacyCqrsDispatchHandlerBase.cs (1)
14-17: ⚡ Quick win
PrepareTarget缺少<param>与<exception>XML 文档
PrepareTarget的 XML 注释缺少对参数和可抛异常的说明。该方法对target为 null 抛ArgumentNullException,对上下文不可用时抛InvalidOperationException——调用方需要这些契约信息。✏️ 建议修复
/// <summary> /// 在执行 legacy 命令或查询前,把当前架构上下文显式注入给支持 <see cref="IContextAware" /> 的目标对象。 /// </summary> + /// <param name="target">待注入上下文的目标对象,不可为 <see langword="null"/>。</param> + /// <exception cref="ArgumentNullException"><paramref name="target"/> 为 <see langword="null"/>。</exception> + /// <exception cref="InvalidOperationException">目标实现了 <see cref="IContextAware"/> 但当前 handler 尚无可用的架构上下文。</exception> protected void PrepareTarget(object target)As per coding guidelines: "XML documentation MUST use
<summary>,<param>,<returns>,<exception>, and<remarks>where applicable".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Cqrs/LegacyCqrsDispatchHandlerBase.cs` around lines 14 - 17, The PrepareTarget method is missing XML doc tags for its parameter and possible exceptions; add <param name="target"> describing the target object and when it must be non-null, and add <exception cref="System.ArgumentNullException"> and <exception cref="System.InvalidOperationException"> entries describing the conditions under which each is thrown (null target and missing/invalid context respectively), keeping the existing <summary> intact and following the project's XML-doc guidelines; reference the PrepareTarget method and the IContextAware interface in the comments to clarify the contract.GFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequest.cs (1)
8-11: ⚡ Quick win补充主构造函数参数的
<param>及ExecuteAsync的<returns>XML 文档类级别 XML 注释缺少
target和executeAsync两个主构造函数参数的<param>标签;ExecuteAsync()方法也缺少<returns>说明。✏️ 建议修复
/// <summary> /// 包装 legacy 异步带返回值命令,使其能够通过自有 CQRS runtime 调度。 /// </summary> +/// <param name="target">bridge request 所代理的 legacy 目标对象,不可为 <see langword="null"/>。</param> +/// <param name="executeAsync">封装 legacy 命令执行逻辑的异步委托,不可为 <see langword="null"/>。</param> internal sealed class LegacyAsyncCommandResultDispatchRequest(object target, Func<Task<object?>> executeAsync)/// <summary> /// 异步执行底层 legacy 命令并返回装箱后的结果。 /// </summary> + /// <returns>legacy 命令执行完成后装箱的返回值;若命令无返回值则为 <see langword="null"/>。</returns> public Task<object?> ExecuteAsync() => _executeAsync();As per coding guidelines: "XML documentation MUST use
<summary>,<param>,<returns>,<exception>, and<remarks>where applicable".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequest.cs` around lines 8 - 11, Add XML documentation for the primary constructor parameters and the ExecuteAsync method: update the class-level comment for LegacyAsyncCommandResultDispatchRequest to include <param name="target"> describing the wrapped legacy command target and <param name="executeAsync"> describing the Func<Task<object?>> execution delegate, and add a <returns> tag to the ExecuteAsync() method describing the returned Task<object?> (what the task represents and nullability). Ensure the tags follow existing XML doc style used in the file.GFramework.Core/Cqrs/LegacyCqrsDispatchRequestBase.cs (1)
6-9: ⚡ Quick win补充主构造函数参数的
<param>XML 文档类级别 XML 注释中缺少对主构造函数参数
target的<param>说明。根据编码规范,所有 public/protected/internal 成员均须包含完整的 XML 文档(<summary>、<param>、<exception>等适用标签)。✏️ 建议修复
/// <summary> /// 为 legacy Command / Query 到自有 CQRS runtime 的桥接请求提供共享的目标对象封装。 /// </summary> +/// <param name="target">bridge request 所代理的 legacy 目标对象,不可为 <see langword="null"/>。</param> +/// <exception cref="ArgumentNullException"><paramref name="target"/> 为 <see langword="null"/>。</exception> internal abstract class LegacyCqrsDispatchRequestBase(object target)As per coding guidelines: "XML documentation MUST use
<summary>,<param>,<returns>,<exception>, and<remarks>where applicable".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Cqrs/LegacyCqrsDispatchRequestBase.cs` around lines 6 - 9, The class XML docs for LegacyCqrsDispatchRequestBase(object target) are missing a <param> entry for the primary constructor parameter; update the class-level XML comment to include a <param name="target">...</param> that briefly describes what the target represents (e.g., the wrapped legacy command/query target object) so the internal abstract class LegacyCqrsDispatchRequestBase and its constructor parameter `target` meet the project's XML documentation requirements.GFramework.Core.Tests/Architectures/LegacyArchitectureBridgeCommand.cs (1)
31-31: 💤 Low value在文件顶部添加
using指令,避免在方法体中使用完全限定类型名第 31 行对
IContextAware使用了完全限定名GFramework.Core.Abstractions.Rule.IContextAware,但该命名空间并未在文件顶部导入。添加一个using可以提升可读性。✏️ 建议修复
using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Command; +using GFramework.Core.Abstractions.Rule; using GFramework.Core.Rule;- ObservedContext = ((GFramework.Core.Abstractions.Rule.IContextAware)this).GetContext(); + ObservedContext = ((IContextAware)this).GetContext();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core.Tests/Architectures/LegacyArchitectureBridgeCommand.cs` at line 31, Add a using directive for the GFramework.Core.Abstractions.Rule namespace at the top of the file so the cast in the ObservedContext assignment can use the short interface name instead of the fully-qualified GFramework.Core.Abstractions.Rule.IContextAware; update the code line using the IContextAware symbol (the cast currently on ObservedContext = ((GFramework.Core.Abstractions.Rule.IContextAware)this).GetContext();) to rely on the imported type for readability.GFramework.Core.Tests/Architectures/LegacyBridgePipelineTracker.cs (1)
31-39: ⚡ Quick win
Record方法使用字符串名称匹配识别 bridge request,存在脆弱性。通过
requestType.Name.Contains("Legacy", StringComparison.Ordinal)来判断请求类型,若将来GFramework.Core.Cqrs命名空间中新增包含 "Legacy" 字样但与 bridge 无关的类型,将产生误计数。建议使用 marker interface 或共同基类进行检测:-if (string.Equals(requestType.Namespace, "GFramework.Core.Cqrs", StringComparison.Ordinal) && - requestType.Name.Contains("Legacy", StringComparison.Ordinal)) +// 推荐:改为检查 marker interface 或公共基类,以替代字符串名称匹配 +if (typeof(ILegacyCqrsBridgeRequest).IsAssignableFrom(requestType))若
LegacyCqrsDispatchRequestBase已是公共基类,也可直接用IsAssignableFrom(requestType)检测。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core.Tests/Architectures/LegacyBridgePipelineTracker.cs` around lines 31 - 39, The current Record method misidentifies bridge requests by string-matching requestType.Name for "Legacy", causing false positives; update the detection to use a type-based check instead: after ArgumentNullException.ThrowIfNull(requestType) replace the namespace+name string condition with an assignability check against a dedicated marker/interface or base class (e.g. typeof(LegacyCqrsDispatchRequestBase).IsAssignableFrom(requestType) or an ILegacyBridgeRequest marker), and only call Interlocked.Increment(ref _invocationCount) when that type-based check succeeds so detection is robust and accurate.GFramework.Core/Query/AsyncQueryExecutor.cs (1)
33-85: ⚡ Quick win建议同样为
TryResolveDispatchContext加[MemberNotNullWhen(true, nameof(_runtime))],顺便去掉_runtime!的强抑制。与
QueryExecutor同构。第 33 行的&& _runtime is not null仅为 nullable 分析,第 52 行的_runtime!也是因为编译器无法跨方法跟踪TryResolveDispatchContext已经验证过_runtime非空。把判空语义沉到TryResolveDispatchContext上后,这两处都可以自然简化。♻️ 建议的改动
+using System.Diagnostics.CodeAnalysis; using GFramework.Core.Abstractions.Query; +using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Rule; using GFramework.Core.Cqrs; using GFramework.Cqrs.Abstractions.Cqrs;- if (TryResolveDispatchContext(query, out var context) && _runtime is not null) + if (TryResolveDispatchContext(query, out var context)) { return BridgeAsyncQueryAsync<TResult>(context, query); }private async Task<TResult> BridgeAsyncQueryAsync<TResult>( - GFramework.Core.Abstractions.Architectures.IArchitectureContext context, + IArchitectureContext context, IAsyncQuery<TResult> query) { - var boxedResult = await _runtime!.SendAsync( + // Caller guarantees _runtime is non-null via TryResolveDispatchContext. + var boxedResult = await _runtime!.SendAsync(- private bool TryResolveDispatchContext(object query, out GFramework.Core.Abstractions.Architectures.IArchitectureContext context) + [MemberNotNullWhen(true, nameof(_runtime))] + private bool TryResolveDispatchContext(object query, [NotNullWhen(true)] out IArchitectureContext? context) { - context = null!; + context = null; ... }As per coding guidelines: "Write null-safe code that respects nullable annotations instead of suppressing warnings by default in C#".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Query/AsyncQueryExecutor.cs` around lines 33 - 85, Add the nullable annotation to TryResolveDispatchContext so the compiler knows _runtime is non-null when it returns true: annotate the method with [MemberNotNullWhen(true, nameof(_runtime))] (import System.Diagnostics.CodeAnalysis), keep its behavior, then remove the redundant null-check "&& _runtime is not null" at the call site and drop the null-forcing operator from _runtime! inside BridgeAsyncQueryAsync so calls use _runtime directly (refer to TryResolveDispatchContext, BridgeAsyncQueryAsync, and the _runtime field).GFramework.Core/Query/QueryExecutor.cs (1)
38-78: ⚡ Quick win建议为
TryResolveDispatchContext加上[MemberNotNullWhen(true, nameof(_runtime))],以消除调用点的重复_runtime is not null判空。
TryResolveDispatchContext在_runtime is null时已经返回false(第 64 行),因此 38 行的&& _runtime is not null实际上只是为了配合 nullable flow 分析,让编译器在第 40 行不报警。用MemberNotNullWhen把这个语义显式声明出来,既能去掉重复判空,也能让后续别的调用点直接从TryResolveDispatchContext拿到_runtime已经非空的事实。♻️ 建议的改动
+using System.Diagnostics.CodeAnalysis; using GFramework.Core.Abstractions.Query; +using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Rule; using GFramework.Core.Cqrs; using GFramework.Cqrs.Abstractions.Cqrs;- if (TryResolveDispatchContext(query, out var context) && _runtime is not null) + if (TryResolveDispatchContext(query, out var context)) { var boxedResult = _runtime.SendAsync( context, ...- private bool TryResolveDispatchContext(object query, out GFramework.Core.Abstractions.Architectures.IArchitectureContext context) + [MemberNotNullWhen(true, nameof(_runtime))] + private bool TryResolveDispatchContext(object query, [NotNullWhen(true)] out IArchitectureContext? context) { - context = null!; + context = null; if (_runtime is null || query is not IContextAware contextAware) { return false; } try { context = contextAware.GetContext(); return true; } catch (InvalidOperationException) { return false; } }As per coding guidelines: "Write null-safe code that respects nullable annotations instead of suppressing warnings by default in C#".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Query/QueryExecutor.cs` around lines 38 - 78, Add the nullable flow attribute to TryResolveDispatchContext and remove the redundant check at the call site: annotate the method TryResolveDispatchContext with [MemberNotNullWhen(true, nameof(_runtime))] so the compiler knows that when it returns true _runtime is non-null, then update the caller in the method that currently checks "if (TryResolveDispatchContext(query, out var context) && _runtime is not null)" to just "if (TryResolveDispatchContext(query, out var context))" (remove the && _runtime is not null) so the nullable analysis no longer requires the duplicate null check.GFramework.Core/Command/CommandExecutor.cs (1)
80-202: ⚡ Quick win建议把
_runtime非空语义沉到TryResolveDispatchContext,统一收敛四处重复判空与一处 null-forgiving。第 80 / 99 / 121 / 147 行都重复了
TryResolveDispatchContext已经覆盖过的_runtime is null判断,BridgeAsyncCommandWithResultAsync(第 169 行)也只能借助_runtime!跨方法抑制 nullable 警告。给TryResolveDispatchContext加[MemberNotNullWhen(true, nameof(_runtime))]后,所有if (TryResolveDispatchContext(...) && _runtime is not null)都可以收敛为单条件,helper 内的负向分支也可以简化。♻️ 建议的改动
+using System.Diagnostics.CodeAnalysis; using GFramework.Core.Abstractions.Command; +using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Rule; using GFramework.Core.Cqrs; using GFramework.Cqrs.Abstractions.Cqrs;- if (TryResolveDispatchContext(command, out var context) && _runtime is not null) + if (TryResolveDispatchContext(command, out var context)) { return _runtime.SendAsync(context, new LegacyAsyncCommandDispatchRequest(command)).AsTask(); }- private bool TryExecuteThroughCqrsRuntime<TTarget, TRequest>( + private bool TryExecuteThroughCqrsRuntime<TTarget, TRequest>( TTarget target, Func<TTarget, TRequest> requestFactory) where TTarget : class where TRequest : IRequest<Unit> { - if (!TryResolveDispatchContext(target, out var context) || _runtime is null) + if (!TryResolveDispatchContext(target, out var context)) { return false; } _runtime.SendAsync(context, requestFactory(target)).AsTask().GetAwaiter().GetResult(); return true; }- private bool TryResolveDispatchContext(object target, out GFramework.Core.Abstractions.Architectures.IArchitectureContext context) + [MemberNotNullWhen(true, nameof(_runtime))] + private bool TryResolveDispatchContext(object target, [NotNullWhen(true)] out IArchitectureContext? context) { - context = null!; + context = null; ... }类比修改也适用于
TryExecuteThroughCqrsRuntime<TTarget, TResult, TRequest>与BridgeAsyncCommandWithResultAsync(可去掉_runtime!)。As per coding guidelines: "Write null-safe code that respects nullable annotations instead of suppressing warnings by default in C#".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Command/CommandExecutor.cs` around lines 80 - 202, The helper TryResolveDispatchContext currently duplicates null checks for _runtime and forces null-forgiving on usages; annotate TryResolveDispatchContext with [MemberNotNullWhen(true, nameof(_runtime))] (import System.Diagnostics.CodeAnalysis), adjust its signature/logic to assert _runtime non-null when it returns true, then remove redundant "_runtime is not null" guards in callers (SendAsync, SendAsync<TResult>, TryExecuteThroughCqrsRuntime<TTarget,TRequest>, TryExecuteThroughCqrsRuntime<TTarget,TResult,TRequest>) so each just calls TryResolveDispatchContext(...) and uses _runtime without the null-forgiving operator (e.g. remove _runtime! and simplify conditions to a single TryResolveDispatchContext check).GFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs (1)
31-31: 💤 Low value外层 benchmark 类可以加
sealed。仓库中其它 benchmark 模式(以及
Config内嵌类自身)都用了sealed。RequestLifetimeBenchmarks不需要被继承,封闭后既能与已有约定保持一致,又能让运行时省掉一次虚分发候选检查。-public class RequestLifetimeBenchmarks +public sealed class RequestLifetimeBenchmarks🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs` at line 31, 将公有基准类 RequestLifetimeBenchmarks 标记为 sealed:在类声明处添加 sealed 关键字以阻止继承并与仓库中其它基准类/内嵌 Config 类保持一致,从而消除不必要的虚调用开销(修改类 RequestLifetimeBenchmarks 的声明即可)。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/zh-CN/core/command.md`:
- Around line 108-110: 在这段文档中补充一行关于回退条件的说明,明确指出尽管标准架构入口会走
ICqrsRuntime,但在隔离测试或未注入 runtime 的场景(例如直接 new CommandExecutor() 而未提供 runtime
实例)会回退到 legacy
直接执行语义;请在描述中使用相同术语(ICqrsRuntime、CommandExecutor、pipeline/上下文注入)并说明行为一致性与副作用(pipeline
不被注入、使用旧的执行路径)。
In `@docs/zh-CN/core/context.md`:
- Around line 114-116: Augment the paragraph to explicitly state that
AsyncQueryExecutor (and the SendQueryAsync compatibility entry) follows the same
fallback rule: when you directly instantiate AsyncQueryExecutor without
providing an ICqrsRuntime it will fall back to legacy direct execution just like
new CommandExecutor() / new QueryExecutor(); update the text to mention
AsyncQueryExecutor and SendQueryAsync by name so readers know the same “no
runtime => legacy direct execution” boundary applies to all three executors.
In `@GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs`:
- Around line 264-289: RegisterLegacyBridgeHandlers currently uses string-based
reflection and Activator.CreateInstance for the six handler types
(LegacyCommandDispatchRequestHandler, LegacyCommandResultDispatchRequestHandler,
LegacyAsyncCommandDispatchRequestHandler,
LegacyAsyncCommandResultDispatchRequestHandler,
LegacyQueryDispatchRequestHandler, LegacyAsyncQueryDispatchRequestHandler),
which is brittle; add an InternalsVisibleTo("GFramework.Core.Tests") attribute
in GFramework.Core/Properties/AssemblyInfo.cs so the test assembly can access
internal types, then replace the reflection/Activator logic in
RegisterLegacyBridgeHandlers (in ArchitectureContextTests.cs) with direct
instantiation and container.RegisterPlurality(new
LegacyCommandDispatchRequestHandler()) etc. to get compile-time safety against
renames.
In `@GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs`:
- Around line 89-113: The test leaves the architecture initialized if any
assertion fails because await architecture.DestroyAsync() runs after
Assert.Multiple; wrap the assertion block in a try/finally (or
try/catch/finally) so that await architecture.DestroyAsync() is always executed
in the finally block; keep the existing LegacyBridgeArchitecture instantiation
and calls to InitializeAsync, SendQuery, and SendCommand, but move the cleanup
call (architecture.DestroyAsync()) into the finally to guarantee teardown even
on assertion failures.
In `@GFramework.Core.Tests/Architectures/LegacyBridgePipelineTracker.cs`:
- Around line 11-41: The static field _invocationCount in
LegacyBridgePipelineTracker creates cross-test shared mutable state leading to
flaky parallel tests; update LegacyBridgePipelineTracker by adding a <remarks>
XML doc on the class describing its thread-safety (uses Volatile.Read/Write and
Interlocked.Increment) and lifecycle (process-wide counter used by tests), and
ensure all test fixtures (e.g., ArchitectureContextTests and
ArchitectureModulesBehaviorTests) call LegacyBridgePipelineTracker.Reset() in
their TearDown/OneTimeTearDown to deterministically clear state; also consider
documenting that InvocationCount is safe for concurrent reads/writes because
Record uses Interlocked and Reset uses Volatile.Write.
In `@GFramework.Core/Cqrs/LegacyAsyncCommandDispatchRequest.cs`:
- Around line 12-18: The null check in the auto-property initializer for Command
is unreachable because LegacyCqrsDispatchRequestBase's constructor already
throws for a null target; remove the "= command ?? throw new
ArgumentNullException(nameof(command))" initializer and instead assign the
parameter directly to the Command auto-property (or rely on the base check) so
you don't duplicate unreachable validation, and add the missing XML
documentation param tag for "command" on the LegacyAsyncCommandDispatchRequest
record-like declaration to match the fix applied in
LegacyCommandDispatchRequest.cs.
In `@GFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequestHandler.cs`:
- Around line 15-22: Handle currently ignores the CancellationToken; mirror the
fix from LegacyAsyncQueryDispatchRequestHandler by calling
cancellationToken.ThrowIfCancellationRequested() before executing and awaiting
request.ExecuteAsync() with cancellation support via
.WaitAsync(cancellationToken); update
LegacyAsyncCommandResultDispatchRequestHandler.Handle (which calls
PrepareTarget(request.Target) and request.ExecuteAsync()) to await
request.ExecuteAsync().WaitAsync(cancellationToken) (and keep ConfigureAwait if
used) so the operation respects cancellation.
In `@GFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequestHandler.cs`:
- Around line 15-22: The Handle method in LegacyAsyncQueryDispatchRequestHandler
ignores the CancellationToken; before awaiting request.ExecuteAsync() add a
cancellation check (e.g., cancellationToken.ThrowIfCancellationRequested()) and,
where appropriate, await request.ExecuteAsync().WaitAsync(cancellationToken) so
the caller's await can observe cancellation earlier (note this won't cancel the
underlying Task), and update any downstream calls (e.g., PrepareTarget or any
IAsyncQuery<T>.DoAsync() overloads if they can accept a token) to accept and
forward the cancellationToken; if downstream cannot accept a token, ensure you
poll/throw on cancellation before invoking them.
In `@GFramework.Core/Cqrs/LegacyCommandDispatchRequest.cs`:
- Around line 12-18: The Command property initializer in
LegacyCommandDispatchRequest contains an unreachable null-check and misleading
exception name because the base constructor
LegacyCqrsDispatchRequestBase(command) already throws for null (using "target");
remove the redundant "command ?? throw..." check from the Command get; instead
rely on the base validation (or, if you prefer derived-class validation, move
the null check into the LegacyCommandDispatchRequest primary constructor and
remove it from the base), and add a class-level XML <param name="command"> entry
to document the constructor parameter; refer to LegacyCommandDispatchRequest,
LegacyCqrsDispatchRequestBase, and the Command property when making the change.
In `@GFramework.Core/Cqrs/LegacyCommandResultDispatchRequest.cs`:
- Around line 11-14: Add XML documentation to the primary constructor of
LegacyCommandResultDispatchRequest: include a <summary> describing the purpose
of this constructor and add <param name="target"> and <param name="execute">
tags that explain the target object and the delegate used to execute the command
(mention nullability/behaviour if relevant); also add any applicable <returns>
or <remarks> if the constructor's behaviour warrants it. Locate the constructor
on the LegacyCommandResultDispatchRequest type and update its XML comments
accordingly.
In `@GFramework.Core/Cqrs/LegacyQueryDispatchRequest.cs`:
- Around line 16-19: The Execute() method on LegacyQueryDispatchRequest lacks a
<returns> XML doc tag; add an XML <returns> element to the Execute() method
summary that succinctly states it returns the boxed legacy query result
(object?), e.g. describe that it returns the boxed/nullable result of the
underlying legacy query produced by _execute(); update the XML comment above
public object? Execute() => _execute(); accordingly.
---
Outside diff comments:
In `@GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs`:
- Around line 35-40: TearDown currently clears GameContext and resets
TrackingPipelineBehavior<ModuleBehaviorRequest, string>.InvocationCount but
forgets to reset LegacyBridgePipelineTracker; update the TearDown method to also
reset the LegacyBridgePipelineTracker's count/state (the static counter or
relevant reset method on LegacyBridgePipelineTracker) so tests don't leak state
between runs.
In `@GFramework.Core/Services/Modules/AsyncQueryExecutorModule.cs`:
- Around line 33-40: 为 Register 方法补全 XML 文档:在现有 <summary> 和 <param> 之外加入
<exception> 标记说明当 container 为 null 时会抛出 ArgumentNullException,以及当无法解析
ICqrsRuntime 时可能抛出的 InvalidOperationException(或容器特定的解析异常);在 <remarks>
中说明该方法会从容器解析 ICqrsRuntime 并以多例/瞬态形式注册 AsyncQueryExecutor,强调调用方必须先在容器中注册
ICqrsRuntime(或等效运行时)以避免解析失败,并注明注册语义(多例/Transient)。
In `@GFramework.Core/Services/Modules/CommandExecutorModule.cs`:
- Around line 33-40: 为 Register(IIocContainer) 方法补充完整 XML
注释,说明方法行为、参数约束和可能抛出的异常:在 <summary> 里描述“将 CommandExecutor 注册为多例服务”;在 <param
name="container"> 中说明必须非空且实现 IIocContainer;新增 <exception
cref="ArgumentNullException"> 说明当 container 为 null 时会抛出(因内部使用
ArgumentNullException.ThrowIfNull);新增 <remarks> 或 <returns>(如适用)说明内部会通过
container.Get<ICqrsRuntime>() 获取依赖并因此要求容器能解析 ICqrsRuntime。确保引用的方法/类型名为 Register,
IIocContainer, CommandExecutor, ArgumentNullException.ThrowIfNull,
container.Get<ICqrsRuntime>() 以便在文档中清晰指出调用契约。
In `@GFramework.Core/Services/Modules/QueryExecutorModule.cs`:
- Around line 33-40: Update the XML documentation for
QueryExecutorModule.Register to include an <exception> that documents
ArgumentNullException thrown when the container is null and to explicitly state
that this method resolves an ICqrsRuntime from the container; in the <remarks>
describe the precondition that an ICqrsRuntime implementation must be registered
in the IIocContainer before calling Register (since the method constructs new
QueryExecutor(container.Get<ICqrsRuntime>()) and registers it via
container.RegisterPlurality). Ensure <summary> and <param name="container">
remain, and mention the behavior of creating and registering a QueryExecutor
instance.
---
Nitpick comments:
In `@GFramework.Core.Tests/Architectures/LegacyArchitectureBridgeCommand.cs`:
- Line 31: Add a using directive for the GFramework.Core.Abstractions.Rule
namespace at the top of the file so the cast in the ObservedContext assignment
can use the short interface name instead of the fully-qualified
GFramework.Core.Abstractions.Rule.IContextAware; update the code line using the
IContextAware symbol (the cast currently on ObservedContext =
((GFramework.Core.Abstractions.Rule.IContextAware)this).GetContext();) to rely
on the imported type for readability.
In `@GFramework.Core.Tests/Architectures/LegacyBridgePipelineTracker.cs`:
- Around line 31-39: The current Record method misidentifies bridge requests by
string-matching requestType.Name for "Legacy", causing false positives; update
the detection to use a type-based check instead: after
ArgumentNullException.ThrowIfNull(requestType) replace the namespace+name string
condition with an assignability check against a dedicated marker/interface or
base class (e.g.
typeof(LegacyCqrsDispatchRequestBase).IsAssignableFrom(requestType) or an
ILegacyBridgeRequest marker), and only call Interlocked.Increment(ref
_invocationCount) when that type-based check succeeds so detection is robust and
accurate.
In `@GFramework.Core/Command/CommandExecutor.cs`:
- Around line 80-202: The helper TryResolveDispatchContext currently duplicates
null checks for _runtime and forces null-forgiving on usages; annotate
TryResolveDispatchContext with [MemberNotNullWhen(true, nameof(_runtime))]
(import System.Diagnostics.CodeAnalysis), adjust its signature/logic to assert
_runtime non-null when it returns true, then remove redundant "_runtime is not
null" guards in callers (SendAsync, SendAsync<TResult>,
TryExecuteThroughCqrsRuntime<TTarget,TRequest>,
TryExecuteThroughCqrsRuntime<TTarget,TResult,TRequest>) so each just calls
TryResolveDispatchContext(...) and uses _runtime without the null-forgiving
operator (e.g. remove _runtime! and simplify conditions to a single
TryResolveDispatchContext check).
In `@GFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequest.cs`:
- Around line 8-11: Add XML documentation for the primary constructor parameters
and the ExecuteAsync method: update the class-level comment for
LegacyAsyncCommandResultDispatchRequest to include <param name="target">
describing the wrapped legacy command target and <param name="executeAsync">
describing the Func<Task<object?>> execution delegate, and add a <returns> tag
to the ExecuteAsync() method describing the returned Task<object?> (what the
task represents and nullability). Ensure the tags follow existing XML doc style
used in the file.
In `@GFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequest.cs`:
- Around line 8-11: 为 LegacyAsyncQueryDispatchRequest 的主构造函数补充 XML 文档中的 <param>
标签,分别说明 target(被包装的目标对象或处理者)和 executeAsync(执行查询的委托,返回 Task<object?>)的含义;同时在
ExecuteAsync 方法的 XML 注释中添加 <returns>,明确返回值是 Task<object?>(表示异步查询结果或 null);参照
LegacyAsyncCommandResultDispatchRequest 的注释样式确保使用 <summary>、<param> 和 <returns>
并在注释中使用类名 LegacyAsyncQueryDispatchRequest 和方法名 ExecuteAsync 作为定位参考。
In `@GFramework.Core/Cqrs/LegacyCqrsDispatchHandlerBase.cs`:
- Around line 14-17: The PrepareTarget method is missing XML doc tags for its
parameter and possible exceptions; add <param name="target"> describing the
target object and when it must be non-null, and add <exception
cref="System.ArgumentNullException"> and <exception
cref="System.InvalidOperationException"> entries describing the conditions under
which each is thrown (null target and missing/invalid context respectively),
keeping the existing <summary> intact and following the project's XML-doc
guidelines; reference the PrepareTarget method and the IContextAware interface
in the comments to clarify the contract.
In `@GFramework.Core/Cqrs/LegacyCqrsDispatchRequestBase.cs`:
- Around line 6-9: The class XML docs for LegacyCqrsDispatchRequestBase(object
target) are missing a <param> entry for the primary constructor parameter;
update the class-level XML comment to include a <param name="target">...</param>
that briefly describes what the target represents (e.g., the wrapped legacy
command/query target object) so the internal abstract class
LegacyCqrsDispatchRequestBase and its constructor parameter `target` meet the
project's XML documentation requirements.
In `@GFramework.Core/Query/AsyncQueryExecutor.cs`:
- Around line 33-85: Add the nullable annotation to TryResolveDispatchContext so
the compiler knows _runtime is non-null when it returns true: annotate the
method with [MemberNotNullWhen(true, nameof(_runtime))] (import
System.Diagnostics.CodeAnalysis), keep its behavior, then remove the redundant
null-check "&& _runtime is not null" at the call site and drop the null-forcing
operator from _runtime! inside BridgeAsyncQueryAsync so calls use _runtime
directly (refer to TryResolveDispatchContext, BridgeAsyncQueryAsync, and the
_runtime field).
In `@GFramework.Core/Query/QueryExecutor.cs`:
- Around line 38-78: Add the nullable flow attribute to
TryResolveDispatchContext and remove the redundant check at the call site:
annotate the method TryResolveDispatchContext with [MemberNotNullWhen(true,
nameof(_runtime))] so the compiler knows that when it returns true _runtime is
non-null, then update the caller in the method that currently checks "if
(TryResolveDispatchContext(query, out var context) && _runtime is not null)" to
just "if (TryResolveDispatchContext(query, out var context))" (remove the &&
_runtime is not null) so the nullable analysis no longer requires the duplicate
null check.
In `@GFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs`:
- Line 31: 将公有基准类 RequestLifetimeBenchmarks 标记为 sealed:在类声明处添加 sealed
关键字以阻止继承并与仓库中其它基准类/内嵌 Config 类保持一致,从而消除不必要的虚调用开销(修改类 RequestLifetimeBenchmarks
的声明即可)。
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 911e6939-d992-4be9-a36a-850606ec4ce2
📒 Files selected for processing (38)
GFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Core.Tests/Architectures/LegacyArchitectureBridgeAsyncQuery.csGFramework.Core.Tests/Architectures/LegacyArchitectureBridgeCommand.csGFramework.Core.Tests/Architectures/LegacyArchitectureBridgeCommandWithResult.csGFramework.Core.Tests/Architectures/LegacyArchitectureBridgeQuery.csGFramework.Core.Tests/Architectures/LegacyBridgePipelineTracker.csGFramework.Core.Tests/Architectures/LegacyBridgeTrackingPipelineBehavior.csGFramework.Core/Architectures/ArchitectureContext.csGFramework.Core/Command/CommandExecutor.csGFramework.Core/Cqrs/LegacyAsyncCommandDispatchRequest.csGFramework.Core/Cqrs/LegacyAsyncCommandDispatchRequestHandler.csGFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequest.csGFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequestHandler.csGFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequest.csGFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequestHandler.csGFramework.Core/Cqrs/LegacyCommandDispatchRequest.csGFramework.Core/Cqrs/LegacyCommandDispatchRequestHandler.csGFramework.Core/Cqrs/LegacyCommandResultDispatchRequest.csGFramework.Core/Cqrs/LegacyCommandResultDispatchRequestHandler.csGFramework.Core/Cqrs/LegacyCqrsDispatchHandlerBase.csGFramework.Core/Cqrs/LegacyCqrsDispatchRequestBase.csGFramework.Core/Cqrs/LegacyQueryDispatchRequest.csGFramework.Core/Cqrs/LegacyQueryDispatchRequestHandler.csGFramework.Core/Query/AsyncQueryExecutor.csGFramework.Core/Query/QueryExecutor.csGFramework.Core/README.mdGFramework.Core/Services/Modules/AsyncQueryExecutorModule.csGFramework.Core/Services/Modules/CommandExecutorModule.csGFramework.Core/Services/Modules/QueryExecutorModule.csGFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.csGFramework.Cqrs.Benchmarks/README.mdai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.mdai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mddocs/zh-CN/core/command.mddocs/zh-CN/core/context.mddocs/zh-CN/core/cqrs.mddocs/zh-CN/core/query.md
- 修复 legacy bridge 测试装配与清理流程,改用 InternalsVisibleTo 和显式 handler 注册,补齐共享计数器重置与生命周期说明 - 优化 CommandExecutor、QueryExecutor 与相关模块的 runtime 契约,补充 XML 文档、nullable 注解和显式依赖解析 - 更新 legacy 异步 bridge 的取消语义、兼容文档回退边界以及 cqrs-rewrite active tracking/trace
Summary
Test ResultsDetails
Insights
build-and-test: Run #1078
🎉 All tests passed!Slowest Tests
± Comparison with run #1077 at 277d3a5 | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 29 runs. Github Test Reporter by CTRF 💚 |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (2)
GFramework.Core/Query/QueryExecutor.cs (1)
62-82: ⚡ Quick win
TryResolveDispatchContext与CommandExecutor中存在完全相同的副本两个密封类各自维护一份逻辑完全相同的私有辅助方法,违反 DRY 原则。未来任一侧的改动(例如新增对
OperationCanceledException的处理)都需要同步到另一处,存在静默漂移的风险。建议提取为共享的静态辅助类,例如
LegacyCqrsDispatchHelper:♻️ 提取到共享静态辅助类
// GFramework.Core/Cqrs/LegacyCqrsDispatchHelper.cs internal static class LegacyCqrsDispatchHelper { /// <summary>解析 legacy 对象所绑定的架构上下文,供 CQRS runtime bridge 使用。</summary> [MemberNotNullWhen(true, "runtime")] // 字符串形式,因为是静态方法参数而非成员 internal static bool TryResolveDispatchContext( ICqrsRuntime? runtime, object target, out IArchitectureContext context) { context = null!; if (runtime is null || target is not IContextAware contextAware) return false; try { context = contextAware.GetContext(); return true; } catch (InvalidOperationException) { return false; } } }然后在
QueryExecutor和CommandExecutor中统一调用:- [MemberNotNullWhen(true, nameof(_runtime))] - private bool TryResolveDispatchContext(object query, out IArchitectureContext context) - { ... } + // 委托给共享辅助方法 + private bool TryResolveDispatchContext(object query, out IArchitectureContext context) + => LegacyCqrsDispatchHelper.TryResolveDispatchContext(_runtime, query, out context);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Query/QueryExecutor.cs` around lines 62 - 82, There are duplicate private implementations of TryResolveDispatchContext in QueryExecutor and CommandExecutor; extract the logic into a single internal static helper (e.g., LegacyCqrsDispatchHelper) with a signature like TryResolveDispatchContext(ICqrsRuntime? runtime, object target, out IArchitectureContext context) and [MemberNotNullWhen(true, "runtime")] on the method, move the try/catch and type check there, and replace the private methods in QueryExecutor and CommandExecutor to call LegacyCqrsDispatchHelper.TryResolveDispatchContext(runtime, queryOrCommand, out context) so both classes share the same implementation.GFramework.Core/Command/CommandExecutor.cs (1)
188-208: ⚡ Quick win
TryResolveDispatchContext与QueryExecutor中的私有辅助方法逻辑完全相同两处实现逐行一致,存在同步漂移风险。此处与
QueryExecutor.cs中提出的提取建议为同一根因,建议统一提取到LegacyCqrsDispatchHelper静态类中(详见QueryExecutor.cs的 review 注释)。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Command/CommandExecutor.cs` around lines 188 - 208, Extract the duplicated logic in TryResolveDispatchContext from CommandExecutor.cs and the identical helper in QueryExecutor.cs into a single static helper class LegacyCqrsDispatchHelper with a method like TryResolveDispatchContext(object target, object? runtime, out GFramework.Core.Abstractions.Architectures.IArchitectureContext context); implement the same behavior: set context = null!, return false if runtime is null or target is not IContextAware, otherwise call ((IContextAware)target).GetContext() in a try/catch that returns false on InvalidOperationException and true on success; then replace the private helpers in CommandExecutor and QueryExecutor to call LegacyCqrsDispatchHelper.TryResolveDispatchContext passing their _runtime and target.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs`:
- Around line 149-160: The test relies on the shared static
LegacyBridgePipelineTracker.InvocationCount which causes race conditions when
tests run in parallel; to fix this, mark the test fixture (the class containing
SendQuery_Should_Bridge_Through_CqrsRuntime_And_Preserve_Context) with the NUnit
[NonParallelizable] attribute so the fixture runs sequentially; update the class
declaration that contains ArchitectureContextTests (and ensure the NUnit
attribute namespace is available) rather than changing the individual test,
leaving the existing TearDown Reset() in place.
- Around line 263-272: CreateFrozenBridgeContext currently instantiates a
MicrosoftDiContainer and wraps it in an ArchitectureContext without exposing or
disposing the container, leaking IDisposable registrations; modify the API so
the created container is owned and disposed by tests or ArchitectureContext:
either change CreateFrozenBridgeContext to return both the ArchitectureContext
and the underlying MicrosoftDiContainer (e.g., via an out parameter) so callers
can call Dispose on the container after the test, or update
ArchitectureContext's constructor to accept ownership and implement IDisposable
forwarding to dispose the inner MicrosoftDiContainer; update tests to acquire
the container (or rely on ArchitectureContext.Dispose) and ensure it's disposed
in a finally/TearDown block.
In `@GFramework.Core/Command/CommandExecutor.cs`:
- Around line 116-157: Both overloads TryExecuteThroughCqrsRuntime (the two
methods that call _runtime.SendAsync(...).AsTask().GetAwaiter().GetResult())
perform sync-over-async and risk deadlock under a SynchronizationContext; fix
both occurrences by either changing the ICqrsRuntime.SendAsync contract to
guarantee ConfigureAwait(false) is applied through the call chain, or wrap the
SendAsync call in Task.Run(...) and block on that task to isolate it from the
current SynchronizationContext (e.g., replace direct
.AsTask().GetAwaiter().GetResult() with Task.Run(() =>
_runtime.SendAsync(...).AsTask()).GetAwaiter().GetResult()); apply the same fix
to both TryExecuteThroughCqrsRuntime<TTarget,TRequest> and
TryExecuteThroughCqrsRuntime<TTarget,TResult,TRequest> to match the mitigation
used in QueryExecutor.
In `@GFramework.Core/Query/QueryExecutor.cs`:
- Line 49: The XML docs for the method in class QueryExecutor that returns
"(TResult)boxedResult!" must be expanded: update the <returns> to state the
method returns the unboxed TResult on success and add two <exception> tags
documenting that a NullReferenceException may be thrown when boxedResult is null
and TResult is a value type, and an InvalidCastException may be thrown when the
actual type of boxedResult cannot be cast to TResult; modify the XML comment
immediately above the method containing the cast to include these <returns> and
<exception> entries referencing QueryExecutor and that specific method.
- Around line 41-49: The current sync-over-async call in QueryExecutor (the call
to _runtime.SendAsync(...).AsTask().GetAwaiter().GetResult() that constructs
LegacyQueryDispatchRequest with query.Do()) can deadlock when a
SynchronizationContext is present; either update the XML <remarks> for
ICqrsRuntime to explicitly require all implementers and handlers to use
ConfigureAwait(false) throughout the async chain, or change QueryExecutor to
offload the blocking wait to the thread pool (e.g., wrap the async call in
Task.Run and await its result synchronously) to prevent capturing the caller's
sync context; locate the SendAsync usage in QueryExecutor and apply one of these
fixes, and also document the chosen contract on ICqrsRuntime and related handler
interfaces (mentioning ICqrsRuntime, QueryExecutor, LegacyQueryDispatchRequest,
and query.Do) so implementers are aware.
---
Nitpick comments:
In `@GFramework.Core/Command/CommandExecutor.cs`:
- Around line 188-208: Extract the duplicated logic in TryResolveDispatchContext
from CommandExecutor.cs and the identical helper in QueryExecutor.cs into a
single static helper class LegacyCqrsDispatchHelper with a method like
TryResolveDispatchContext(object target, object? runtime, out
GFramework.Core.Abstractions.Architectures.IArchitectureContext context);
implement the same behavior: set context = null!, return false if runtime is
null or target is not IContextAware, otherwise call
((IContextAware)target).GetContext() in a try/catch that returns false on
InvalidOperationException and true on success; then replace the private helpers
in CommandExecutor and QueryExecutor to call
LegacyCqrsDispatchHelper.TryResolveDispatchContext passing their _runtime and
target.
In `@GFramework.Core/Query/QueryExecutor.cs`:
- Around line 62-82: There are duplicate private implementations of
TryResolveDispatchContext in QueryExecutor and CommandExecutor; extract the
logic into a single internal static helper (e.g., LegacyCqrsDispatchHelper) with
a signature like TryResolveDispatchContext(ICqrsRuntime? runtime, object target,
out IArchitectureContext context) and [MemberNotNullWhen(true, "runtime")] on
the method, move the try/catch and type check there, and replace the private
methods in QueryExecutor and CommandExecutor to call
LegacyCqrsDispatchHelper.TryResolveDispatchContext(runtime, queryOrCommand, out
context) so both classes share the same implementation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7c094ef7-cd81-47b5-817f-b5d5129f4d75
📒 Files selected for processing (24)
GFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Core.Tests/Architectures/LegacyBridgePipelineTracker.csGFramework.Core/Command/CommandExecutor.csGFramework.Core/Cqrs/LegacyAsyncCommandDispatchRequest.csGFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequest.csGFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequestHandler.csGFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequest.csGFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequestHandler.csGFramework.Core/Cqrs/LegacyCommandDispatchRequest.csGFramework.Core/Cqrs/LegacyCommandResultDispatchRequest.csGFramework.Core/Cqrs/LegacyCqrsDispatchHandlerBase.csGFramework.Core/Cqrs/LegacyCqrsDispatchRequestBase.csGFramework.Core/Cqrs/LegacyQueryDispatchRequest.csGFramework.Core/Properties/AssemblyInfo.csGFramework.Core/Query/AsyncQueryExecutor.csGFramework.Core/Query/QueryExecutor.csGFramework.Core/Services/Modules/AsyncQueryExecutorModule.csGFramework.Core/Services/Modules/CommandExecutorModule.csGFramework.Core/Services/Modules/QueryExecutorModule.csai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.mdai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mddocs/zh-CN/core/command.mddocs/zh-CN/core/context.md
✅ Files skipped from review due to trivial changes (6)
- GFramework.Core/Cqrs/LegacyCqrsDispatchRequestBase.cs
- docs/zh-CN/core/context.md
- GFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequest.cs
- GFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequest.cs
- GFramework.Core/Cqrs/LegacyAsyncCommandDispatchRequest.cs
- GFramework.Core/Properties/AssemblyInfo.cs
🚧 Files skipped from review as they are similar to previous changes (12)
- GFramework.Core/Cqrs/LegacyCqrsDispatchHandlerBase.cs
- GFramework.Core/Cqrs/LegacyCommandDispatchRequest.cs
- GFramework.Core.Tests/Architectures/LegacyBridgePipelineTracker.cs
- GFramework.Core/Services/Modules/AsyncQueryExecutorModule.cs
- GFramework.Core/Cqrs/LegacyAsyncCommandResultDispatchRequestHandler.cs
- GFramework.Core/Cqrs/LegacyCommandResultDispatchRequest.cs
- GFramework.Core/Services/Modules/CommandExecutorModule.cs
- GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
- GFramework.Core/Cqrs/LegacyAsyncQueryDispatchRequestHandler.cs
- GFramework.Core/Cqrs/LegacyQueryDispatchRequest.cs
- GFramework.Core/Query/AsyncQueryExecutor.cs
- ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (C#)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.cs: Apply [Log] attribute for automatic logging field and logging helper method generation
Apply [Priority] attribute for automatic priority comparison implementation generation
Apply [GenerateEnumExtensions] attribute to generate enumeration extension capabilities
Apply [ContextAware] attribute to automatically implement IContextAware boilerplate logic
**/*.cs: All public, protected, and internal types and members MUST include XML documentation comments (///) in C#
XML documentation MUST use<summary>,<param>,<returns>,<exception>, and<remarks>where applicable, and explain intent, contract, and usage constraints instead of restating syntax
If a C# member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly
Core framework components (Architecture, Module, System, Context, Registry, Service Module, Lifecycle types) MUST include high-level explanations of responsibilities, lifecycle, interaction with other components, why abstraction exists, and when to use instead of alternatives
Generated logic and source generator pipelines MUST explain what is generated, why it is generated, semantic assumptions the generator relies on, and any diagnostics or fallback behavior
Do not rely on implicit imports. Declare every requiredusingexplicitly in C#
Write null-safe code that respects nullable annotations instead of suppressing warnings by default in C#
Use namespace patternGFramework.{Module}.{Feature}with PascalCase segments in C#
Follow standard C# naming: Types/methods/properties/events/constants use PascalCase, Interfaces useIprefix, Parameters and locals use camelCase, Private fields use_camelCase
Use Allman braces style for C#
Keepusingdirectives at the top of the file and sort them consistently in C#
Prefer one primary type per file unless surrounding project already uses different local pattern
Prefer explicit, readable code over clever shorthand in framework internals
M...
Files:
GFramework.Core/Services/Modules/QueryExecutorModule.csGFramework.Core/Query/QueryExecutor.csGFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core/Command/CommandExecutor.cs
**/*[!.]*
📄 CodeRabbit inference engine (AGENTS.md)
For files with shebang lines, keep shebang as first line and place license header immediately after it
Files:
GFramework.Core/Services/Modules/QueryExecutorModule.csGFramework.Core/Query/QueryExecutor.csGFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core/Command/CommandExecutor.csai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mddocs/zh-CN/core/command.md
**/*.{cs,ts,tsx,js,jsx,py,sh}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{cs,ts,tsx,js,jsx,py,sh}: All generated or modified code MUST include clear and meaningful comments where required by documentation rules
Comments MUST NOT be trivial, redundant, or misleading. Prefer explainingwhyandwhen, not justwhat. Code should remain understandable without requiring external context
Avoid obvious comments such as// increment i
Files:
GFramework.Core/Services/Modules/QueryExecutorModule.csGFramework.Core/Query/QueryExecutor.csGFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core/Command/CommandExecutor.cs
**/*.{cs,ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{cs,ts,tsx,js,jsx,py}: Add inline comments for non-trivial logic, concurrency/threading behavior, performance-sensitive paths, workarounds/compatibility constraints/edge cases, and registration order/lifecycle sequencing/generated code assumptions
Methods with non-trivial logic MUST document core idea, key decisions, and edge case handling
Separate logical blocks with blank lines when it improves readability
Unless there is clear and documented reason to keep file large, keep single source file under roughly 800-1000 lines
Validate external or user-controlled input before it reaches file system, serialization, reflection, code generation, or process boundaries
Do not build command strings, file paths, type names, or generated code from untrusted input without strict validation or allow-listing
Avoid logging secrets, tokens, credentials, or machine-specific sensitive data
Prefer least-privilege behavior for file, process, and environment access
Files:
GFramework.Core/Services/Modules/QueryExecutorModule.csGFramework.Core/Query/QueryExecutor.csGFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core/Command/CommandExecutor.cs
**/*.{csproj,cs}
📄 CodeRabbit inference engine (AGENTS.md)
Framework runtime, abstractions, and meta-package projects MUST NOT reference
*.SourceGenerators*projects or packages, and MUST NOT use source-generator attributes
Files:
GFramework.Core/Services/Modules/QueryExecutorModule.csGFramework.Core/Query/QueryExecutor.csGFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core/Command/CommandExecutor.cs
**/*.{cs,ts,tsx,js,jsx,py,sh,xml,csproj,props,targets}
📄 CodeRabbit inference engine (AGENTS.md)
Use 4 spaces for indentation. Do not use tabs
Files:
GFramework.Core/Services/Modules/QueryExecutorModule.csGFramework.Core/Query/QueryExecutor.csGFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core/Command/CommandExecutor.cs
**/*.{cs,ts,tsx,js,jsx,py,sh,xml}
📄 CodeRabbit inference engine (AGENTS.md)
Keep line length readable. Around 120 characters is preferred upper bound
Files:
GFramework.Core/Services/Modules/QueryExecutorModule.csGFramework.Core/Query/QueryExecutor.csGFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core/Command/CommandExecutor.cs
**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{md,mdx}: Keep code samples, package names, and command examples aligned with current repository state in documentation
When public page references XML docs or API coverage, convert evidence into reader-facing guidance: explain which types/namespaces/entry points readers should inspect and why
For integration-oriented features such as AI-First config system, documentation MUST cover: project directory layout/file conventions, required project/package wiring, minimal working example, migration/compatibility notes
When examples are rewritten, preserve only parts that remain true. Delete or replace speculative examples instead of lightly editing into another inaccurate form
Files:
ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mddocs/zh-CN/core/command.md
docs/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Documentation should be organized with Chinese content in docs/zh-CN/ and structured to include getting started, module-specific capabilities (Core, Game, Godot, ECS), source generator usage, tutorials, best practices, and troubleshooting
Files:
docs/zh-CN/core/command.md
🧠 Learnings (1)
📚 Learning: 2026-04-06T12:45:43.921Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 190
File: GFramework.Game/Config/GameConfigBootstrap.cs:1-3
Timestamp: 2026-04-06T12:45:43.921Z
Learning: In the GeWuYou/GFramework repository, C# files may omit explicit `using System*` imports because the project-wide `GlobalUsings.cs` (referenced via manual global `using` directives) supplies common namespaces (e.g., `System`, `System.Threading`, `System.Threading.Tasks`). During code review, do not flag missing `using System...` directives in `.cs` files as long as `GlobalUsings.cs` is present/used to provide those namespaces.
Applied to files:
GFramework.Core/Services/Modules/QueryExecutorModule.csGFramework.Core/Query/QueryExecutor.csGFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core/Command/CommandExecutor.cs
🪛 LanguageTool
docs/zh-CN/core/command.md
[uncategorized] ~110-~110: 您的意思是“"不"上下文”?
Context: ...会回退到 legacy 直接执行;此时不会注入统一 pipeline,也不会额外补上下文桥接链路。 在 IContextAware 对象内,通常直接通过扩展...
(BU)
🔇 Additional comments (4)
GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs (1)
278-288:RegisterLegacyBridgeHandlers已改为直接构造——解决了上一轮反馈的维护风险之前通过字符串字面量反射实例化 handler 的脆弱做法已替换为类型安全的直接构造,重命名时可由编译器感知。
docs/zh-CN/core/command.md (1)
108-111: "发送入口"fallback 说明已补全——解决了上一轮反馈Lines 108–110 现在清晰描述了标准路径走
ICqrsRuntime,以及直接new CommandExecutor()隔离场景下回退 legacy 直执行的行为与限制,与代码实现保持一致。ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md (1)
5-35: RP-094 迁移追踪与本 PR 实际改动一致追踪记录准确反映了本轮决策:直接构造 bridge handler、TearDown 清理、
GetRequired<ICqrsRuntime>()前置约束文档化,以及[MemberNotNullWhen]的引入。GFramework.Core/Services/Modules/QueryExecutorModule.cs (1)
45-49: 注册顺序已正确保证。CqrsRuntimeModule的 Priority 值为 15,低于QueryExecutorModule的 30,框架会确保CqrsRuntimeModule优先完成注册。因此container.GetRequired<ICqrsRuntime>()在注册阶段能安全获取依赖项,无需额外的错误处理或验证逻辑。XML 文档已清楚说明此约束。
- 修复 legacy 同步 bridge 的 runtime 等待方式,统一通过共享 helper 隔离同步上下文并收口重复 dispatch-context 解析逻辑 - 补充 legacy async command bridge 的取消可见性,并更新 ICqrsRuntime 与相关入口的契约说明 - 新增 bridge 回归测试并更新 cqrs-rewrite active tracking,覆盖同步上下文隔离、测试容器释放与取消语义
Summary
Test ResultsDetails
Insights
build-and-test: Run #1079
🎉 All tests passed!Slowest Tests
± Comparison with run #1078 at e9aad4a | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 30 runs. Github Test Reporter by CTRF 💚 |
- 更新 active tracking 与 trace 到 RP-096,记录 latest-head review 的最新权威结论 - 补充 PR #334 当前 stale open thread、CI 测试与 MegaLinter 噪音的本地复核结果
Summary
Test ResultsDetails
Insights
build-and-test: Run #1080
🎉 All tests passed!Slowest Tests
± Comparison with run #1079 at 3fa3f2c | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 31 runs. Github Test Reporter by CTRF 💚 |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md (1)
100-103:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win建议将非当前锚点验证记录迁移到归档段落。
这里仍保留了“确认对应
PR#331”的记录,与当前活跃锚点 `PR `#334并置,容易让“最近权威验证”被误读为多锚点状态。建议移动到历史归档或明确标注“历史验证”。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md` around lines 100 - 103, The note listing verification for "PR `#331`" is mixing a historical check with the active anchor "PR `#334`"; move the non-current anchor verification line (the bullet containing `确认当前分支对应 PR `#331`` and its related remarks) out of the active verification area into a clearly marked "历史归档" or prepend an explicit "历史验证" label so the active anchor section only contains items for PR `#334`; ensure the moved text preserves the original command context (the `python3 .agents/...fetch_current_pr_review.py` bullet) and any result/notes but is relocated to an archive subsection.
🧹 Nitpick comments (3)
GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs (1)
145-163: ⚡ Quick win测试名声明“保留上下文”,但断言未覆盖该行为。
当前只校验了返回值与 request 类型,建议再补一条上下文保留断言(例如断言 query 的观测上下文或 runtime 记录的 context 等于
expectedContext),避免该回归点失守。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs` around lines 145 - 163, The test SendAsync_Should_Bridge_Through_Runtime_And_Preserve_Context currently omits asserting that the context passed into ContextAwareLegacyAsyncQuery is preserved; update the Assert.Multiple block to include an assertion that the context on the dispatched request or the query's observed context equals expectedContext (e.g., assert that runtime.LastRequest.Context or whatever property RecordingCqrsRuntime records matches expectedContext or that the ContextAwareLegacyAsyncQuery instance reports expectedContext after SetContext); this ensures AsyncQueryExecutor and RecordingCqrsRuntime actually preserve and forward the context.GFramework.Core.Tests/Command/CommandExecutorTests.cs (1)
112-130: ⚡ Quick win“保留上下文注入”应增加可观察断言。
该用例标题与注释都强调 context preservation,但目前仅验证返回值和请求类型。建议补充对上下文注入结果的断言,确保该行为有回归保护。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core.Tests/Command/CommandExecutorTests.cs` around lines 112 - 130, Add an assertion that verifies the context was actually preserved/passed through: after calling executor.Send(command) assert that the runtime/dispatch request captured by RecordingCqrsRuntime (inspect runtime.LastRequest or the specific GFramework.Core.Cqrs.LegacyCommandResultDispatchRequest instance) contains the same TestArchitectureContextBaseStub instance set via ((GFramework.Core.Abstractions.Rule.IContextAware)command).SetContext(expectedContext); update the test Send_WithResult_Should_Bridge_Through_Runtime_And_Preserve_Context to include this context-equality/assertion so the context preservation behavior is covered.GFramework.Core.Tests/Command/RecordingCqrsRuntime.cs (1)
39-46: ⚡ Quick win建议对响应解包增加显式类型校验,提升测试失败可诊断性。
当前直接强转在工厂返回类型不匹配时错误信息不够聚焦,建议先做 null/类型检查后抛出带上下文的异常。
可参考的最小改动
object? response = request switch { IRequest<Unit> => Unit.Value, _ => _responseFactory(request) }; - - return ValueTask.FromResult((TResponse)response!); + if (response is null) + { + if (default(TResponse) is null) + { + return ValueTask.FromResult((TResponse)response!); + } + + throw new InvalidOperationException( + $"RecordingCqrsRuntime 无法将 null 转换为值类型 {typeof(TResponse).FullName}。"); + } + + if (response is not TResponse typedResponse) + { + throw new InvalidOperationException( + $"RecordingCqrsRuntime 期望响应类型 {typeof(TResponse).FullName},实际为 {response.GetType().FullName}。"); + } + + return ValueTask.FromResult(typedResponse);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core.Tests/Command/RecordingCqrsRuntime.cs` around lines 39 - 46, The test runtime method in RecordingCqrsRuntime currently casts the factory result directly ((TResponse)response!) which yields poor diagnostics on failure; update the logic in the method that computes response (the switch returning Unit.Value or _responseFactory(request)) to perform an explicit null and type check before casting: if response is null throw an ArgumentNullException with context (include request type and expected TResponse), if response is not TResponse throw an InvalidCastException or custom InvalidOperationException with a message that includes the request type, actual response type and expected TResponse; use the symbols _responseFactory and the containing method in RecordingCqrsRuntime to locate where to add these checks and then return ValueTask.FromResult((TResponse)response) after validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md`:
- Around line 100-103: The note listing verification for "PR `#331`" is mixing a
historical check with the active anchor "PR `#334`"; move the non-current anchor
verification line (the bullet containing `确认当前分支对应 PR `#331`` and its related
remarks) out of the active verification area into a clearly marked "历史归档" or
prepend an explicit "历史验证" label so the active anchor section only contains
items for PR `#334`; ensure the moved text preserves the original command context
(the `python3 .agents/...fetch_current_pr_review.py` bullet) and any
result/notes but is relocated to an archive subsection.
---
Nitpick comments:
In `@GFramework.Core.Tests/Command/CommandExecutorTests.cs`:
- Around line 112-130: Add an assertion that verifies the context was actually
preserved/passed through: after calling executor.Send(command) assert that the
runtime/dispatch request captured by RecordingCqrsRuntime (inspect
runtime.LastRequest or the specific
GFramework.Core.Cqrs.LegacyCommandResultDispatchRequest instance) contains the
same TestArchitectureContextBaseStub instance set via
((GFramework.Core.Abstractions.Rule.IContextAware)command).SetContext(expectedContext);
update the test
Send_WithResult_Should_Bridge_Through_Runtime_And_Preserve_Context to include
this context-equality/assertion so the context preservation behavior is covered.
In `@GFramework.Core.Tests/Command/RecordingCqrsRuntime.cs`:
- Around line 39-46: The test runtime method in RecordingCqrsRuntime currently
casts the factory result directly ((TResponse)response!) which yields poor
diagnostics on failure; update the logic in the method that computes response
(the switch returning Unit.Value or _responseFactory(request)) to perform an
explicit null and type check before casting: if response is null throw an
ArgumentNullException with context (include request type and expected
TResponse), if response is not TResponse throw an InvalidCastException or custom
InvalidOperationException with a message that includes the request type, actual
response type and expected TResponse; use the symbols _responseFactory and the
containing method in RecordingCqrsRuntime to locate where to add these checks
and then return ValueTask.FromResult((TResponse)response) after validation.
In `@GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs`:
- Around line 145-163: The test
SendAsync_Should_Bridge_Through_Runtime_And_Preserve_Context currently omits
asserting that the context passed into ContextAwareLegacyAsyncQuery is
preserved; update the Assert.Multiple block to include an assertion that the
context on the dispatched request or the query's observed context equals
expectedContext (e.g., assert that runtime.LastRequest.Context or whatever
property RecordingCqrsRuntime records matches expectedContext or that the
ContextAwareLegacyAsyncQuery instance reports expectedContext after SetContext);
this ensures AsyncQueryExecutor and RecordingCqrsRuntime actually preserve and
forward the context.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d1e5babd-708d-4b71-818c-08995ca5ee48
📒 Files selected for processing (21)
GFramework.Core.Tests/Architectures/ArchitectureContextTests.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Core.Tests/Command/CommandExecutorTests.csGFramework.Core.Tests/Command/ContextAwareLegacyCommand.csGFramework.Core.Tests/Command/ContextAwareLegacyCommandWithResult.csGFramework.Core.Tests/Command/RecordingCqrsRuntime.csGFramework.Core.Tests/Command/TestLegacySynchronizationContext.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.csGFramework.Core.Tests/Query/AsyncQueryExecutorTests.csGFramework.Core.Tests/Query/ContextAwareLegacyAsyncQuery.csGFramework.Core.Tests/Query/ContextAwareLegacyQuery.csGFramework.Core.Tests/Query/QueryExecutorTests.csGFramework.Core/Architectures/ArchitectureContext.csGFramework.Core/Command/CommandExecutor.csGFramework.Core/Cqrs/LegacyAsyncCommandDispatchRequestHandler.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core/Query/AsyncQueryExecutor.csGFramework.Core/Query/QueryExecutor.csGFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.mdai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
✅ Files skipped from review due to trivial changes (3)
- GFramework.Core.Tests/Command/ContextAwareLegacyCommandWithResult.cs
- GFramework.Core.Tests/Query/ContextAwareLegacyAsyncQuery.cs
- GFramework.Core.Tests/Command/ContextAwareLegacyCommand.cs
🚧 Files skipped from review as they are similar to previous changes (6)
- GFramework.Core/Cqrs/LegacyAsyncCommandDispatchRequestHandler.cs
- GFramework.Core/Query/QueryExecutor.cs
- GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
- GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs
- GFramework.Core/Query/AsyncQueryExecutor.cs
- GFramework.Core/Architectures/ArchitectureContext.cs
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (C#)
🧰 Additional context used
📓 Path-based instructions (10)
**/*Abstractions/**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
Abstractions projects should only contain interfaces and contract definitions without any runtime implementation logic
Files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.cs
**/Cqrs/**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
Use CQRS (Command Query Responsibility Segregation) pattern with the Cqrs naming entry point instead of the historical Mediator alias
Files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.cs
**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.cs: Apply [Log] attribute for automatic logging field and logging helper method generation
Apply [Priority] attribute for automatic priority comparison implementation generation
Apply [GenerateEnumExtensions] attribute to generate enumeration extension capabilities
Apply [ContextAware] attribute to automatically implement IContextAware boilerplate logic
**/*.cs: All public, protected, and internal types and members MUST include XML documentation comments (///) in C#
XML documentation MUST use<summary>,<param>,<returns>,<exception>, and<remarks>where applicable, and explain intent, contract, and usage constraints instead of restating syntax
If a C# member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly
Core framework components (Architecture, Module, System, Context, Registry, Service Module, Lifecycle types) MUST include high-level explanations of responsibilities, lifecycle, interaction with other components, why abstraction exists, and when to use instead of alternatives
Generated logic and source generator pipelines MUST explain what is generated, why it is generated, semantic assumptions the generator relies on, and any diagnostics or fallback behavior
Do not rely on implicit imports. Declare every requiredusingexplicitly in C#
Write null-safe code that respects nullable annotations instead of suppressing warnings by default in C#
Use namespace patternGFramework.{Module}.{Feature}with PascalCase segments in C#
Follow standard C# naming: Types/methods/properties/events/constants use PascalCase, Interfaces useIprefix, Parameters and locals use camelCase, Private fields use_camelCase
Use Allman braces style for C#
Keepusingdirectives at the top of the file and sort them consistently in C#
Prefer one primary type per file unless surrounding project already uses different local pattern
Prefer explicit, readable code over clever shorthand in framework internals
M...
Files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csGFramework.Core.Tests/Query/ContextAwareLegacyQuery.csGFramework.Core.Tests/Command/TestLegacySynchronizationContext.csGFramework.Core.Tests/Query/AsyncQueryExecutorTests.csGFramework.Core.Tests/Command/CommandExecutorTests.csGFramework.Core.Tests/Query/QueryExecutorTests.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.csGFramework.Core.Tests/Command/RecordingCqrsRuntime.csGFramework.Core/Command/CommandExecutor.cs
**/*[!.]*
📄 CodeRabbit inference engine (AGENTS.md)
For files with shebang lines, keep shebang as first line and place license header immediately after it
Files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csGFramework.Core.Tests/Query/ContextAwareLegacyQuery.csGFramework.Core.Tests/Command/TestLegacySynchronizationContext.csGFramework.Core.Tests/Query/AsyncQueryExecutorTests.csGFramework.Core.Tests/Command/CommandExecutorTests.csGFramework.Core.Tests/Query/QueryExecutorTests.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.csGFramework.Core.Tests/Command/RecordingCqrsRuntime.csGFramework.Core/Command/CommandExecutor.csai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.mdai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
**/*.{cs,ts,tsx,js,jsx,py,sh}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{cs,ts,tsx,js,jsx,py,sh}: All generated or modified code MUST include clear and meaningful comments where required by documentation rules
Comments MUST NOT be trivial, redundant, or misleading. Prefer explainingwhyandwhen, not justwhat. Code should remain understandable without requiring external context
Avoid obvious comments such as// increment i
Files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csGFramework.Core.Tests/Query/ContextAwareLegacyQuery.csGFramework.Core.Tests/Command/TestLegacySynchronizationContext.csGFramework.Core.Tests/Query/AsyncQueryExecutorTests.csGFramework.Core.Tests/Command/CommandExecutorTests.csGFramework.Core.Tests/Query/QueryExecutorTests.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.csGFramework.Core.Tests/Command/RecordingCqrsRuntime.csGFramework.Core/Command/CommandExecutor.cs
**/*.{cs,ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{cs,ts,tsx,js,jsx,py}: Add inline comments for non-trivial logic, concurrency/threading behavior, performance-sensitive paths, workarounds/compatibility constraints/edge cases, and registration order/lifecycle sequencing/generated code assumptions
Methods with non-trivial logic MUST document core idea, key decisions, and edge case handling
Separate logical blocks with blank lines when it improves readability
Unless there is clear and documented reason to keep file large, keep single source file under roughly 800-1000 lines
Validate external or user-controlled input before it reaches file system, serialization, reflection, code generation, or process boundaries
Do not build command strings, file paths, type names, or generated code from untrusted input without strict validation or allow-listing
Avoid logging secrets, tokens, credentials, or machine-specific sensitive data
Prefer least-privilege behavior for file, process, and environment access
Files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csGFramework.Core.Tests/Query/ContextAwareLegacyQuery.csGFramework.Core.Tests/Command/TestLegacySynchronizationContext.csGFramework.Core.Tests/Query/AsyncQueryExecutorTests.csGFramework.Core.Tests/Command/CommandExecutorTests.csGFramework.Core.Tests/Query/QueryExecutorTests.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.csGFramework.Core.Tests/Command/RecordingCqrsRuntime.csGFramework.Core/Command/CommandExecutor.cs
**/*.{csproj,cs}
📄 CodeRabbit inference engine (AGENTS.md)
Framework runtime, abstractions, and meta-package projects MUST NOT reference
*.SourceGenerators*projects or packages, and MUST NOT use source-generator attributes
Files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csGFramework.Core.Tests/Query/ContextAwareLegacyQuery.csGFramework.Core.Tests/Command/TestLegacySynchronizationContext.csGFramework.Core.Tests/Query/AsyncQueryExecutorTests.csGFramework.Core.Tests/Command/CommandExecutorTests.csGFramework.Core.Tests/Query/QueryExecutorTests.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.csGFramework.Core.Tests/Command/RecordingCqrsRuntime.csGFramework.Core/Command/CommandExecutor.cs
**/*.{cs,ts,tsx,js,jsx,py,sh,xml,csproj,props,targets}
📄 CodeRabbit inference engine (AGENTS.md)
Use 4 spaces for indentation. Do not use tabs
Files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csGFramework.Core.Tests/Query/ContextAwareLegacyQuery.csGFramework.Core.Tests/Command/TestLegacySynchronizationContext.csGFramework.Core.Tests/Query/AsyncQueryExecutorTests.csGFramework.Core.Tests/Command/CommandExecutorTests.csGFramework.Core.Tests/Query/QueryExecutorTests.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.csGFramework.Core.Tests/Command/RecordingCqrsRuntime.csGFramework.Core/Command/CommandExecutor.cs
**/*.{cs,ts,tsx,js,jsx,py,sh,xml}
📄 CodeRabbit inference engine (AGENTS.md)
Keep line length readable. Around 120 characters is preferred upper bound
Files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csGFramework.Core.Tests/Query/ContextAwareLegacyQuery.csGFramework.Core.Tests/Command/TestLegacySynchronizationContext.csGFramework.Core.Tests/Query/AsyncQueryExecutorTests.csGFramework.Core.Tests/Command/CommandExecutorTests.csGFramework.Core.Tests/Query/QueryExecutorTests.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.csGFramework.Core.Tests/Command/RecordingCqrsRuntime.csGFramework.Core/Command/CommandExecutor.cs
**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{md,mdx}: Keep code samples, package names, and command examples aligned with current repository state in documentation
When public page references XML docs or API coverage, convert evidence into reader-facing guidance: explain which types/namespaces/entry points readers should inspect and why
For integration-oriented features such as AI-First config system, documentation MUST cover: project directory layout/file conventions, required project/package wiring, minimal working example, migration/compatibility notes
When examples are rewritten, preserve only parts that remain true. Delete or replace speculative examples instead of lightly editing into another inaccurate form
Files:
ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.mdai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
🧠 Learnings (1)
📚 Learning: 2026-04-06T12:45:43.921Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 190
File: GFramework.Game/Config/GameConfigBootstrap.cs:1-3
Timestamp: 2026-04-06T12:45:43.921Z
Learning: In the GeWuYou/GFramework repository, C# files may omit explicit `using System*` imports because the project-wide `GlobalUsings.cs` (referenced via manual global `using` directives) supplies common namespaces (e.g., `System`, `System.Threading`, `System.Threading.Tasks`). During code review, do not flag missing `using System...` directives in `.cs` files as long as `GlobalUsings.cs` is present/used to provide those namespaces.
Applied to files:
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.csGFramework.Core.Tests/Query/ContextAwareLegacyQuery.csGFramework.Core.Tests/Command/TestLegacySynchronizationContext.csGFramework.Core.Tests/Query/AsyncQueryExecutorTests.csGFramework.Core.Tests/Command/CommandExecutorTests.csGFramework.Core.Tests/Query/QueryExecutorTests.csGFramework.Core/Cqrs/LegacyCqrsDispatchHelper.csGFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.csGFramework.Core.Tests/Command/RecordingCqrsRuntime.csGFramework.Core/Command/CommandExecutor.cs
🪛 LanguageTool
ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
[grammar] ~48-~48: Ensure spelling is correct
Context: ...、QueryExecutor 的同步 CQRS/legacy bridge 入口不再直接在调用线程上阻塞 SendAsync(...).GetAwaiter().GetResult() - GFramework.Core.Tests 现通过 `InternalsVisibleTo("GFramework.Core.Te...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
[grammar] ~5-~5: Ensure spelling is correct
Context: ... 2026-05-07 ### 阶段:PR #334 latest-head review 复核(CQRS-REWRITE-RP-096) - 再次使用 `$gframework-pr...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~22-~22: Ensure spelling is correct
Context: ...## 阶段:PR #334 legacy bridge sync follow-up(CQRS-REWRITE-RP-095) - 再次使用 `$gframework-pr...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~30-~30: Ensure spelling is correct
Context: ... bridge 对 ICqrsRuntime.SendAsync(...) 的线程池隔离等待 - 将 QueryExecutor、CommandExecutor、`Asyn...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~31-~31: Ensure spelling is correct
Context: ...elper,并把 ArchitectureContext 的同步 CQRS 包装入口一并切换到同一阻塞策略,避免留下半修状态 - 为 ICqrsRuntime.SendAsync(...) 补充 ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🔇 Additional comments (7)
GFramework.Core.Tests/Command/TestLegacySynchronizationContext.cs (1)
6-11: 实现清晰,符合测试占位用途。该占位
SynchronizationContext类型足够轻量,且注释说明了使用场景。GFramework.Core.Tests/Query/ContextAwareLegacyQuery.cs (1)
13-25: 测试替身设计合理。通过
ObservedContext暴露执行期上下文,能有效支撑 bridge 上下文注入断言。GFramework.Core.Tests/Cqrs/LegacyAsyncCommandDispatchRequestHandlerTests.cs (1)
21-61: 取消语义回归覆盖到位。两条用例分别锁定“执行前取消”和“执行中取消”,对 bridge handler 的行为约束很有价值。
GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.cs (1)
31-34: 契约备注补充准确。把 legacy 同步入口的等待策略与
SynchronizationContext约束写进接口文档,能减少实现偏差。GFramework.Core.Tests/Query/QueryExecutorTests.cs (1)
67-98: 测试对同步桥接行为的回归保护很完整。这里同时验证了返回值、runtime 请求类型、以及
SynchronizationContext未被复用,覆盖点准确。GFramework.Core/Cqrs/LegacyCqrsDispatchHelper.cs (1)
12-19: 同步桥接辅助的设计与文档说明一致,落地清晰。上下文解析与同步等待策略职责划分明确,便于在 legacy 入口复用统一 pipeline。
Also applies to: 63-93
GFramework.Core/Command/CommandExecutor.cs (1)
38-67: runtime 桥接与 legacy 回退的执行路径拆分得很干净。同步/异步两条链路都先尝试统一 runtime,再安全回退 legacy,整体可维护性和兼容性都不错。
Also applies to: 79-107, 110-185
- 补充 AsyncQueryExecutor 与 CommandExecutor bridge 测试的上下文保留断言 - 优化 RecordingCqrsRuntime 的 bridge 执行模拟与响应类型诊断 - 更新 cqrs-rewrite active tracking 与 trace 的 RP-097 验证记录
Summary
Test ResultsDetails
Insights
build-and-test: Run #1081
🎉 All tests passed!Slowest Tests
± Comparison with run #1080 at 006fbd4 | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 32 runs. Github Test Reporter by CTRF 💚 |
- 修复 LegacyCqrsDispatchHelper 仅在上下文缺失时回退,避免吞掉真实 InvalidOperationException - 补充 CommandExecutor 与 QueryExecutor 相关回归测试,覆盖 fallback 与异常冒泡语义 - 更新 cqrs-rewrite 跟踪与追踪文档,记录 PR #334 本轮复核与验证结果
Summary
Test ResultsDetails
Insights
build-and-test: Run #1082
🎉 All tests passed!Slowest Tests
± Comparison with run #1081 at 78f0ca6 | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 33 runs. Github Test Reporter by CTRF 💚 |
Summary by CodeRabbit
发行说明
新特性
测试
性能基准
文档
杂项