Skip to content

Feat/cqrs optimization#340

Merged
GeWuYou merged 3 commits into
mainfrom
feat/cqrs-optimization
May 8, 2026
Merged

Feat/cqrs optimization#340
GeWuYou merged 3 commits into
mainfrom
feat/cqrs-optimization

Conversation

@GeWuYou
Copy link
Copy Markdown
Owner

@GeWuYou GeWuYou commented May 8, 2026

Summary by CodeRabbit

发布说明

  • 新功能

    • 新增容器注册检查方法,支持查询服务是否已注册,无需实例化服务。
  • 性能优化

    • 优化CQRS请求分发热路径,当无管道行为时直接调用处理器。
    • 改进依赖注入日志性能,避免不必要的字符串分配开销。
  • 文档

    • 更新基准测试文档,说明性能对标范围和验证规则。

GeWuYou added 2 commits May 8, 2026 09:41
- 优化 dispatcher 在零 pipeline 场景下跳过空行为解析,减少请求热路径分配

- 修复 MicrosoftDiContainer 热路径的无效 debug 字符串构造,并新增非激活注册检测回归测试

- 新增基于 NuGet 的 Mediator 对照基准并更新 CQRS 重写跟踪文档
- 更新 BenchmarkDotNet 生成目录忽略规则,避免本地基准产物污染工作树

- 补充 CQRS benchmark 回归要求与性能目标,要求相关改动后复跑 request 基准

- 更新 cqrs-rewrite 跟踪文档并记录最新 request 基准结果
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

Review Change Stack

Warning

Rate limit exceeded

@GeWuYou has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 37 minutes and 12 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9afa1ffd-0aee-4846-8a10-7202e6ff783b

📥 Commits

Reviewing files that changed from the base of the PR and between 5da4a58 and 32eeb41.

📒 Files selected for processing (9)
  • GFramework.Core.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs
  • GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs
  • ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
  • ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
  • docs/zh-CN/core/ioc.md
📝 Walkthrough

总体概述

此 PR 优化了 CQRS Request 的热路径性能,通过在 DI 容器引入 HasRegistration(Type) 快速检查能力,使 Dispatcher 能绕过零管道场景。同时扩展基准测试以对标源生成 Mediator 框架,并强化回归管理规范。

变更概览

Request 热路径优化与 Mediator 基准对标

层级 / 文件(s) 摘要
DI 契约定义
GFramework.Core.Abstractions/Ioc/IIocContainer.cs
IIocContainer 接口新增 HasRegistration(Type type) 方法,用于非激活式注册检查。
DI 实现与优化
GFramework.Core/Ioc/MicrosoftDiContainer.cs
MicrosoftDiContainer 实现 HasRegistration 公共 API 与内部核心逻辑,支持开放泛型兼容性检查;在 Get/GetAll 调用时添加 IsDebugEnabled() 保护以减少日志开销。
DI 测试覆盖
GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
新增 HasRegistration 单元测试,验证未注册类型返回 false 与开放泛型匹配返回 true 的行为;包含 HasRegistrationRequest 与 OpenGenericHasRegistrationBehavior 辅助类型。
Dispatcher 零管道优化
GFramework.Cqrs/Internal/CqrsDispatcher.cs
SendAsync 与 CreateStream 在行为解析前检查 container.HasRegistration(BehaviorType),若无注册则直接调用请求/流调用器。
基准设施层
GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj, GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
新增 Mediator.Abstractions v3.0.2 与 Mediator.SourceGenerator v3.0.2 依赖;BenchmarkHostFactory 新增 CreateMediatorServiceProvider 工厂方法。
多框架基准对标
GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs
RequestBenchmarks 扩展至对标四框架(直接处理器、GFramework、MediatR、源生成 Mediator);BenchmarkRequest 与 BenchmarkRequestHandler 实现对应契约;GlobalSetup/Cleanup 管理多个 DI 提供程序。
基准文档与规范
.gitignore, GFramework.Cqrs.Benchmarks/README.md
新增 BenchmarkDotNet.Artifacts/ 忽略规则;README 增加基准作用域说明与"当前约束"章节,文档化产物管理与回归阈值。
规划与跟踪更新
ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md, ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
更新至恢复点 RP-102,文档化 HasRegistration 快速路径、DI 调试守卫、Mediator NuGet 集成、基准回归管理与后续优化方向。

相关 PR

  • GeWuYou/GFramework#326:修改基准设施(BenchmarkHostFactory、RequestBenchmarks、基准项目文件)并引入 DI/HasRegistration 变更和测试以支持零管道/基准场景。

预估代码审查工作量

🎯 3 (中等复杂度) | ⏱️ ~25 分钟

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cqrs-optimization

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

Summary

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Other ❓ Flaky 🍂 Duration ⏱️
2321    ↑2 2320    ↑1 1    ↑1 0 0 0 37.5s    ↓1.8s

Test Results

failed 1 failed ↑1
passed 2320 passed ↑1

Details

tests 2321 tests ↑2
clock 37.5s ↓1.8s
tool nunit
build CI - Build & Test arrow-right build-and-test link #1089
pull-request Feat/cqrs optimization link #340

Failed Tests

CqrsDispatcherContextValidationTests arrow-right CreateStream_Should_Throw_When_Stream_Pipeline_Behavior_Context_Does_Not_Implement_IArchitectureContext

Insights

Average Tests per Run Total Flaky Tests Total Failed Slowest Test (p95)
2224 0 1 4.7s

Fail Rate

Fail Rate 0.00%
Test 📝 Results 📊 Passed ✅ Failed ❌ Fail Rate (%) 📈
CreateStream_Should_Throw_When_Stream_Pipeline_Behavior_Context_Does_Not_Implement_IArchitectureContext 3 2 1 33.33    ↑33.33

build-and-test: Run #1089

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
2321 2320 1 0 0 0 0 37.5s

Some tests failed!

Name Failure Message
❌ CreateStream_Should_Throw_When_Stream_Pipeline_Behavior_Context_Does_Not_Implement_IArchitectureContext Assert.That(() => runtime.CreateStream(new FakeCqrsContext(), new ContextAwareStreamRequest()), Throws.InvalidOperationException.With.Message.Contains("does not implement IArchitectureContext")) Expected: <System.InvalidOperationException> and property Message containing "does not implement IArchitectureContext" But was: <Moq.MockException: IIocContainer.HasRegistration(GFramework.Cqrs.Abstractions.Cqrs.IStreamPipelineBehavior`2[GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherContextValidationTests+ContextAwareStreamRequest,System.Int32]) invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup. at Moq.FailForStrictMock.Handle(Invocation invocation, Mock mock) in /_/src/Moq/Interception/InterceptionAspects.cs:line 182 at Moq.Mock.Moq.IInterceptor.Intercept(Invocation invocation) in /_/src/Moq/Interception/Mock.cs:line 27 at Moq.CastleProxyFactory.Interceptor.Intercept(IInvocation underlying) in /_/src/Moq/Interception/CastleProxyFactory.cs:line 107 at Castle.DynamicProxy.AbstractInvocation.Proceed() at Castle.Proxies.IIocContainerProxy.HasRegistration(Type type) at GFramework.Cqrs.Internal.CqrsDispatcher.CreateStream[TResponse](ICqrsContext context, IStreamRequest`1 request, CancellationToken cancellationToken) in /home/runner/work/GFramework/GFramework/GFramework.Cqrs/Internal/CqrsDispatcher.cs:line 166 at GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherContextValidationTests.<>c__DisplayClass3_0.<CreateStream_Should_Throw_When_Stream_Pipeline_Behavior_Context_Does_Not_Implement_IArchitectureContext>b__1() in /home/runner/work/GFramework/GFramework/GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs:line 106 at InvokeStub_Func`1.Invoke(Object, Object, IntPtr*) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) --- End of stack trace from previous location --- at NUnit.Framework.Internal.ExceptionHelper.Rethrow(Exception exception) at NUnit.Framework.Internal.Reflect.DynamicInvokeWithTransparentExceptions(Delegate delegate) at NUnit.Framework.Internal.ExceptionHelper.RecordException(Delegate parameterlessDelegate, String parameterName)>

Slowest Tests

Test 📝 Results 📊 Duration (avg) ⏱️ Duration (p95) ⏱️
CreateStream_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 21 4.1s 4.7s
SendRequestAsync_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 36 1.7s 4.7s
Does_Not_Report_When_FieldInjectedModel_Is_Registered 36 2.2s 2.3s
Generates_Scene_Behavior_Boilerplate 36 1.9s 2.0s
CleanupDuringAcquire_Should_NotCauseRaceCondition 36 1.1s 1.1s
Append_ShouldNotBlock 36 1.0s 1.0s
Context_Caching_Should_Improve_Performance 36 783ms 795ms
PendingCount_ShouldReflectQueuedEntries 36 501ms 501ms
Cleanup_Should_NotRemoveActiveLocks 36 404ms 405ms
Cleanup_Should_RemoveUnusedLocks 36 401ms 402ms

± Comparison with run #1088 at 01054a9 | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 36 runs.

Github Test Reporter by CTRF 💚

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

⚠️MegaLinter analysis: Success with warnings

Descriptor Linter Files Fixed Errors Warnings Elapsed time
⚠️ CSHARP dotnet-format yes 1 no 5.28s
✅ REPOSITORY gitleaks yes no no 8.81s
✅ REPOSITORY trufflehog yes no no 7.37s

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

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
GFramework.Core.Abstractions/Ioc/IIocContainer.cs (1)

255-265: ⚡ Quick win

补全 HasRegistration(Type) 的异常契约文档。

当前注释缺少 <exception>,但该入口在常见实现中会对空参数和容器释放状态抛异常。建议在接口层显式声明异常契约,避免调用方误判行为边界。

As per coding guidelines "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".

🤖 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.Abstractions/Ioc/IIocContainer.cs` around lines 255 - 265,
Update the XML docs for the HasRegistration(Type) interface method to declare
its exception contract: add <exception> entries for ArgumentNullException
(thrown when the type parameter is null) and ObjectDisposedException (thrown
when the container has been disposed and cannot be queried). Reference the
method name HasRegistration(Type) so implementers and callers know to
document/handle these cases consistently.
GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs (1)

151-173: 💤 Low value

Mediator 与 GFramework 接口隐式共享实现,存在未来契约漂移的编译诊断盲点。

BenchmarkRequestHandler 通过单个公有 Handle(BenchmarkRequest, CancellationToken) : ValueTask<BenchmarkResponse> 同时隐式实现 GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<,>Mediator.IRequestHandler<,>。两个接口的方法签名(包括 ValueTask<TResponse> 返回类型)当前完全一致。

当 Mediator 在主版本升级时若调整 IRequestHandler 签名(例如改为 IRequestHandler<TRequest> 或引入 streaming 区分),单一隐式实现会导致编译错误,且需逐一追踪具体是哪个接口不满足。

建议为 Mediator.IRequestHandler<,>.Handle 添加显式实现仅 => Handle(request, cancellationToken);,使两条契约在源码上分别可见,未来升级时 diff 与诊断更直观。

🤖 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/RequestBenchmarks.cs` around lines 151 -
173, The public Handle(BenchmarkRequest, CancellationToken):
ValueTask<BenchmarkResponse> currently implicitly satisfies both
GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler and Mediator.IRequestHandler
causing a fragile shared implementation; add an explicit implementation for
Mediator.IRequestHandler<BenchmarkRequest, BenchmarkResponse>.Handle that
delegates to the existing public Handle (i.e. implement Task<BenchmarkResponse>
Mediator.IRequestHandler<BenchmarkRequest, BenchmarkResponse>.Handle(...) =>
Handle(request, cancellationToken); or equivalent delegation) so the Mediator
contract is visibly separated while preserving behavior and easing future
diagnostics.
🤖 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 `@ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md`:
- Around line 39-42: 当前文档段落中重复使用了“RP-101”且仍引用旧的 PR 锚点“PR
`#339`”,在当前语境应为“RP-102”且锚点应指向当前 PR;请统一修正恢复点编号并更新活跃入口的 PR 锚点(检查并替换所有出现的
RP-101/RP-102 与 PR `#339/PR` `#340` 引用),删除或替换任何已失效或推测性的示例说明以保持示例准确一致,确保段落开头的 active
入口明确指向最新恢复锚点(例如将 active 入口更新为 RP-102 并把 PR 链接改为 PR `#340`)。

In `@GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs`:
- Around line 79-87: The XML doc comment for the method in BenchmarkHostFactory
(the summary/remarks that currently mention "ai-libs/Mediator") is stale and
should reference the actual NuGet package used; update the summary/param/remarks
to say the project uses the NuGet "Mediator" package (or remove the repo path)
so the documentation matches the implementation that resolves the generated
Mediator.Mediator singleton, e.g., edit the XML doc above the factory method in
class BenchmarkHostFactory to replace "ai-libs/Mediator" with "Mediator (NuGet)"
and keep the rest of the lifetime explanation intact.

---

Nitpick comments:
In `@GFramework.Core.Abstractions/Ioc/IIocContainer.cs`:
- Around line 255-265: Update the XML docs for the HasRegistration(Type)
interface method to declare its exception contract: add <exception> entries for
ArgumentNullException (thrown when the type parameter is null) and
ObjectDisposedException (thrown when the container has been disposed and cannot
be queried). Reference the method name HasRegistration(Type) so implementers and
callers know to document/handle these cases consistently.

In `@GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs`:
- Around line 151-173: The public Handle(BenchmarkRequest, CancellationToken):
ValueTask<BenchmarkResponse> currently implicitly satisfies both
GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler and Mediator.IRequestHandler
causing a fragile shared implementation; add an explicit implementation for
Mediator.IRequestHandler<BenchmarkRequest, BenchmarkResponse>.Handle that
delegates to the existing public Handle (i.e. implement Task<BenchmarkResponse>
Mediator.IRequestHandler<BenchmarkRequest, BenchmarkResponse>.Handle(...) =>
Handle(request, cancellationToken); or equivalent delegation) so the Mediator
contract is visibly separated while preserving behavior and easing future
diagnostics.
🪄 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: 2d7bf93f-eee2-4b68-b0f5-dc8340a4ed05

📥 Commits

Reviewing files that changed from the base of the PR and between 5dc2dd2 and 5da4a58.

📒 Files selected for processing (11)
  • .gitignore
  • GFramework.Core.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs
  • GFramework.Cqrs.Benchmarks/README.md
  • GFramework.Cqrs/Internal/CqrsDispatcher.cs
  • ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
  • ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.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). (3)
  • GitHub Check: Code Quality & Security
  • GitHub Check: Build and Test
  • GitHub Check: Analyze (C#)
🧰 Additional context used
📓 Path-based instructions (11)
**/*Abstractions/**/*.cs

📄 CodeRabbit inference engine (CLAUDE.md)

Abstractions projects should only contain interfaces and contract definitions without any runtime implementation logic

Files:

  • GFramework.Core.Abstractions/Ioc/IIocContainer.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 required using explicitly in C#
Write null-safe code that respects nullable annotations instead of suppressing warnings by default in C#
Use namespace pattern GFramework.{Module}.{Feature} with PascalCase segments in C#
Follow standard C# naming: Types/methods/properties/events/constants use PascalCase, Interfaces use I prefix, Parameters and locals use camelCase, Private fields use _camelCase
Use Allman braces style for C#
Keep using directives 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.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Cqrs/Internal/CqrsDispatcher.cs
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.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.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj
  • GFramework.Cqrs/Internal/CqrsDispatcher.cs
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs
  • GFramework.Cqrs.Benchmarks/README.md
  • ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.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 explaining why and when, not just what. Code should remain understandable without requiring external context
Avoid obvious comments such as // increment i

Files:

  • GFramework.Core.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Cqrs/Internal/CqrsDispatcher.cs
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.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.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Cqrs/Internal/CqrsDispatcher.cs
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.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.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj
  • GFramework.Cqrs/Internal/CqrsDispatcher.cs
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.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.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj
  • GFramework.Cqrs/Internal/CqrsDispatcher.cs
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.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.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Cqrs/Internal/CqrsDispatcher.cs
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs
**/*.{xml,csproj,props,targets}

📄 CodeRabbit inference engine (AGENTS.md)

For XML/MSBuild files with XML declaration, keep XML declaration as first node and place license header immediately after it

Files:

  • GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj
**/*.csproj

📄 CodeRabbit inference engine (AGENTS.md)

**/*.csproj: Follow repository defaults: ImplicitUsings disabled, Nullable enabled, GenerateDocumentationFile enabled for shipped libraries, LangVersion generally preview in main libraries and abstractions
Minimize new package dependencies. Add them only when necessary and keep scope narrow

Files:

  • GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj
**/*.{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.md
  • GFramework.Cqrs.Benchmarks/README.md
  • ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.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.Abstractions/Ioc/IIocContainer.cs
  • GFramework.Cqrs/Internal/CqrsDispatcher.cs
  • GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
  • GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
  • GFramework.Core/Ioc/MicrosoftDiContainer.cs
  • GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs
🔇 Additional comments (3)
GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs (2)

422-446: 测试覆盖到位,闭合泛型 + 开放泛型注册分支语义清晰。

两条用例分别锁定了「无匹配 service 返回 false」与「开放泛型 IPipelineBehavior<,> 注册可被闭合查询命中」两个关键分支,同时验证了 Freeze() 前后 HasRegistration(Type) 的稳定性,恰好对应 PR 在 CqrsDispatcher 里引入的 0 pipeline fast-path 假设。


944-958: 💤 Low value

约束声明一致,OpenGenericHasRegistrationBehavior<TRequest,TResponse> 实现正确。

已确认 IPipelineBehavior<TRequest, TResponse> 的真实声明为:

public interface IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>

约束 where TRequest : IRequest<TResponse> 与 surrogate 类完全一致,因此该实现作为 open-generic registration 的最小代理是恰当的,不存在约束窄化的问题。

GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs (1)

91-95: ⚡ Quick win

BenchmarkCleanupHelper.DisposeAll(...) 已正确引入并支持可空参数列表。

验证确认:

  • BenchmarkCleanupHelper.DisposeAll 的签名为 public static void DisposeAll(params IDisposable?[] disposables),支持可空的 IDisposable?[] 参数
  • 新增的 _mediatorServiceProvider 已正确纳入 cleanup 调用(第 94 行)
  • 该方法设计用于处理多个 IDisposable 对象,包括 MicrosoftDiContainer
  • 异常处理机制文档明确:单个失败回抛原始异常,多个失败聚合为 AggregateException
  • 可空参数类型确保不会因字段未赋值而产生 NRE,避免掩盖真正的失败原因

Comment thread ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md Outdated
Comment thread GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs Outdated
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 8, 2026

Greptile Summary

This PR optimizes the CQRS dispatch hot path and DI logging by introducing HasRegistration(Type) on IIocContainer, letting CqrsDispatcher skip the empty-collection GetAll call when no pipeline behaviors are registered, and adding IsDebugEnabled() guards to eliminate log-string allocations when debug logging is off. A NuGet-based source-generated Mediator comparison group is added to the benchmarks.

  • IIocContainer.HasRegistration(Type) + MicrosoftDiContainer implementation – descriptor-only scan using exact service-key matching and open-generic definition matching, correctly aligned with Get/GetAll resolution semantics; full XML docs and user-facing docs under docs/zh-CN/core/ioc.md are included.
  • CqrsDispatcher fast path – both SendAsync and CreateStream now call HasRegistration first and short-circuit directly to the request/stream invoker when no behaviors exist, reducing allocations from ~440 B to 32 B and latency from ~300 ns to ~83 ns in the zero-pipeline case.
  • Benchmark expansionRequestBenchmarks gains a SendRequest_Mediator method backed by the official Mediator.Abstractions/Mediator.SourceGenerator 3.0.2 NuGet packages, and BenchmarkDotNet.Artifacts/ is added to .gitignore.

Confidence Score: 5/5

Safe to merge — all changes are additive, well-tested, and the core logic has been validated against benchmarks and a full test suite.

The HasRegistration implementation uses a straightforward descriptor-only scan whose semantics are directly verified by three new regression tests (no-match, open-generic, concrete-only self-registration). The CqrsDispatcher fast path is symmetric for request and stream paths, and the strict-mock tests for context validation have been updated to configure the new call. The previous false-positive issue from IsAssignableFrom has been correctly replaced with exact-key and open-generic-definition matching. Benchmark results confirm the allocation and latency improvements are real.

No files require special attention.

Important Files Changed

Filename Overview
GFramework.Cqrs/Internal/CqrsDispatcher.cs Adds HasRegistration fast-path guard before GetAll on both SendAsync and CreateStream hot paths, correctly skipping the empty-collection allocation when no pipeline behaviors are registered.
GFramework.Core/Ioc/MicrosoftDiContainer.cs Implements HasRegistration(Type) via descriptor-only scan (CanSatisfyServiceType), correctly matching exact service keys and open-generic definitions without activating instances; also adds IsDebugEnabled guards to eliminate log-string allocations on hot paths.
GFramework.Core.Abstractions/Ioc/IIocContainer.cs Adds HasRegistration(Type) to the public IIocContainer interface with full XML doc including exception contracts and semantic remarks; companion docs/zh-CN update is included in this PR.
GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs Adds three regression tests for HasRegistration: no-match returns false, open-generic registration is visible, and concrete-only self-registration does not masquerade as its interface keys.
GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs Adds HasRegistration stub configuration to strict mocks for both request and stream context-validation tests, preventing MockException short-circuits before the intended assertion fires.
GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs Adds source-generated Mediator as a fourth comparison group alongside baseline, GFramework.Cqrs, and MediatR; BenchmarkRequest and BenchmarkRequestHandler now explicitly implement Mediator contracts to surface any future API drift at compile time.
GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs Adds CreateMediatorServiceProvider factory for the Mediator NuGet reference; XML doc comment has one line with an extra leading space (harmless formatting noise).

Sequence Diagram

sequenceDiagram
    participant Caller
    participant CqrsDispatcher
    participant IIocContainer
    participant RequestInvoker
    participant PipelineExecutor

    Caller->>CqrsDispatcher: SendAsync(context, request)
    CqrsDispatcher->>IIocContainer: Get(HandlerType)
    IIocContainer-->>CqrsDispatcher: handler

    CqrsDispatcher->>IIocContainer: HasRegistration(BehaviorType)
    alt No behaviors registered (fast path)
        IIocContainer-->>CqrsDispatcher: false
        CqrsDispatcher->>RequestInvoker: Invoke(handler, request, ct)
        RequestInvoker-->>Caller: TResponse (0 behavior allocations)
    else Behaviors registered
        IIocContainer-->>CqrsDispatcher: true
        CqrsDispatcher->>IIocContainer: GetAll(BehaviorType)
        IIocContainer-->>CqrsDispatcher: behaviors[]
        CqrsDispatcher->>PipelineExecutor: GetPipelineExecutor(n).Invoke(...)
        PipelineExecutor-->>Caller: TResponse (pipeline path)
    end
Loading

Reviews (2): Last reviewed commit: "fix(cqrs): 修复 HasRegistration 评审回归" | Re-trigger Greptile

Comment thread GFramework.Core/Ioc/MicrosoftDiContainer.cs
Comment thread GFramework.Core.Abstractions/Ioc/IIocContainer.cs
- 修复 HasRegistration(Type) 的服务键判定,避免将仅按具体类型注册的行为误判为接口已注册

- 补充 strict mock 场景与 HasRegistration 回归测试,并修复 PR #340 暴露的 stream context validation 失败

- 更新 IoC 与 benchmark 文档注释,同步 cqrs-rewrite tracking/trace 到 PR #340 / RP-103
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

Summary

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Other ❓ Flaky 🍂 Duration ⏱️
2322    ↑1 2322    ↑2 0    ↓1 0 0 0 37.0s    ↓544ms

Test Results

passed 2322 passed ↑2

Details

tests 2322 tests ↑1
clock 37.0s ↓544ms
tool nunit
build CI - Build & Test arrow-right build-and-test link #1090
pull-request Feat/cqrs optimization link #340

Insights

Average Tests per Run Total Flaky Tests Total Failed Slowest Test (p95)
2226 0 1 4.7s

Fail Rate

Fail Rate 0.00%
Test 📝 Results 📊 Passed ✅ Failed ❌ Fail Rate (%) 📈
CreateStream_Should_Throw_When_Stream_Pipeline_Behavior_Context_Does_Not_Implement_IArchitectureContext 4 3 1 25.00    ↓8.33

build-and-test: Run #1090

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
2322 2322 0 0 0 0 0 37.0s

🎉 All tests passed!

Slowest Tests

Test 📝 Results 📊 Duration (avg) ⏱️ Duration (p95) ⏱️
CreateStream_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 22 4.1s 4.7s
SendRequestAsync_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 37 1.7s 4.7s
Does_Not_Report_When_FieldInjectedModel_Is_Registered 37 2.2s 2.3s
Generates_Scene_Behavior_Boilerplate 37 1.9s 2.0s
CleanupDuringAcquire_Should_NotCauseRaceCondition 37 1.1s 1.1s
Append_ShouldNotBlock 37 1.0s 1.0s
Context_Caching_Should_Improve_Performance 37 783ms 795ms
PendingCount_ShouldReflectQueuedEntries 37 501ms 501ms
Cleanup_Should_NotRemoveActiveLocks 37 404ms 405ms
Cleanup_Should_RemoveUnusedLocks 37 401ms 402ms

± Comparison with run #1089 at 55b5e87 | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 37 runs.

Github Test Reporter by CTRF 💚

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant