Feat: CQRS dispatcher performance optimization with service cache and benchmark framework#341
Conversation
- 优化 CqrsDispatcher.SendAsync 的 direct-return ValueTask 路径,移除 dispatcher 自身的异步状态机开销 - 引入 MicrosoftDiContainer 冻结后服务键索引,收敛 HasRegistration(Type) 的重复描述符扫描 - 更新 cqrs-rewrite active tracking 与 trace,记录 RP-104 的基线、验证结果与下一批建议
- 新增 handwritten generated request registry,并让默认 RequestBenchmarks 通过真实程序集注册路径接上 generated invoker provider - 补齐 benchmark 最小宿主所需的 CQRS runtime、registrar 与 registration service 基础设施接线 - 更新 CQRS 迁移 tracking 与 trace,记录 RP-105 的 benchmark 结论和当前恢复点
- 新增 request pipeline benchmark 的 handwritten generated request registry,并通过真实程序集注册路径接上 generated invoker provider - 更新 RequestPipelineBenchmarks 宿主接线与 benchmark README,统一默认 request 与 pipeline 场景的 generated-provider 口径 - 更新 CQRS 迁移 tracking 与 trace,记录 RP-106 的基线、验证结果与下一恢复点
- 新增默认 stream benchmark 的 handwritten generated registry,并通过真实程序集注册路径接上 generated stream invoker provider - 更新 StreamingBenchmarks 宿主接线、README 与 RP-107 recovery 文档,统一 request、pipeline、stream 默认宿主口径 - 更新 gframework-boot 与 gframework-batch-boot 技能,改为以上下文预算接近约 80% 为默认优先停止信号
- 新增 stream handler 的 Singleton 和 Transient 生命周期 benchmark,并沿用 generated-provider 宿主接线 - 更新 CQRS benchmark README 与 active ai-plan 恢复点,记录 RP-108 的验证结果和下一步建议
|
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (1)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (2)**/*[!.]*📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{md,mdx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🔇 Additional comments (6)
📝 WalkthroughWalkthrough本 PR:为冻结 DI 容器添加服务类型索引,加速 HasRegistration;将 CqrsDispatcher.SendAsync 改为直接返回 ValueTask(同步异常映射为 faulted ValueTask);在基准主机工厂预注入 CQRS 基础设施并添加多个生成式请求/流注册表;引入 StreamLifetimeBenchmarks;更新若干基准的注册接入与缓存清理;添加/更新相关单元测试、AssemblyInfo 与 SKILL/迁移跟踪文档(上下文预算 ~80% 作为首要停止信号)。 ChangesDI 容器与调度器热路径优化
基准测试基础设施重构
注册器与测试
文档与迁移跟踪
Sequence Diagram(s)sequenceDiagram
participant BenchmarkFactory
participant RegisterHelper
participant DiContainer
participant Logger
BenchmarkFactory->>RegisterHelper: RegisterCqrsInfrastructure(container)
RegisterHelper->>DiContainer: ensure ICqrsRuntime / registrar / registration-service
alt missing generated registry
RegisterHelper->>DiContainer: RegisterGeneratedBenchmarkRegistry<T>()
end
RegisterHelper->>Logger: log registrations
估算代码审查工作量🎯 4 (Complex) | ⏱️ ~60 分钟 可能相关的 PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Summary
Test ResultsDetails
Insights
Fail Rate
build-and-test: Run #1091
🎉 All tests passed!Slowest Tests
± Comparison with run #1090 at b3ceb4e | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 38 runs. Github Test Reporter by CTRF 💚 |
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|
| dotnet-format | yes | 1 | no | 6.33s | ||
| ✅ REPOSITORY | gitleaks | yes | no | no | 8.83s | |
| ✅ REPOSITORY | trufflehog | yes | no | no | 6.95s |
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.Cqrs/Internal/CqrsDispatcher.cs | De-asynced SendAsync hot path; synchronous exceptions now wrapped in ValueTask.FromException to preserve faulted-task semantics. Logic is correct and backed by two new tests. |
| GFramework.Core/Ioc/MicrosoftDiContainer.cs | Adds FrozenServiceTypeIndex cache for HasRegistration after container freeze; semantics verified to be equivalent to HasRegistrationCore/CanSatisfyServiceType (exact + open-generic check). |
| GFramework.Cqrs/Internal/CqrsHandlerRegistrar.cs | New RegisterGeneratedRegistry overload enables targeted single-registry activation without full assembly scan, solving the cross-registry contamination issue flagged in the previous review. |
| GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs | Adds RegisterCqrsInfrastructure and RegisterGeneratedBenchmarkRegistry helpers; INotificationPublisher resolved without null-check before being passed to CqrsRuntimeFactory.CreateRuntime on a fresh container. |
| GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs | New benchmark comparing Singleton vs Transient stream handler dispatch; clean structure with proper setup/cleanup including dispatcher cache clearing. |
| GFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.cs | Intentional no-op Register() to let the benchmark control handler lifetime; the [assembly:CqrsHandlerRegistryAttribute] attribute makes this registry discoverable via full assembly scan, which would register the invoker descriptor without any handler — leading to dispatch failure if assembly scanning is used. |
| GFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.cs | Well-structured generated registry for default request benchmarks; handler registered as singleton, descriptor exposed correctly. |
| GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs | Two new tests verify that SendAsync returns a faulted ValueTask (not a synchronous throw) when context preparation fails or when a handler is missing — correctly validates the de-async behavioral contract. |
| GFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.cs | New test confirms RegisterGeneratedRegistry activates only the selected provider and does not leak other registries from the same assembly. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["SendAsync(context, request, ct)"] --> B{try block}
B --> C[Validate context & request]
C --> D[GetRequestDispatchBinding]
D --> E[container.Get handler]
E --> F{handler found?}
F -- No --> G["throw InvalidOperationException"]
F -- Yes --> H[PrepareHandler]
H --> I{HasRegistration BehaviorType?}
I -- No --> J["return RequestInvoker(...)"]
I -- Yes --> K[GetAll behaviors, PrepareHandler each]
K --> L["return PipelineExecutor(...)"]
G --> M["catch Exception"]
C --> M
D --> M
M --> N["return ValueTask.FromException(ex)"]
subgraph HasRegistration ["HasRegistration - MicrosoftDiContainer"]
R1{frozen?} -- Yes --> R2["FrozenServiceTypeIndex.Contains exact OR open-generic"]
R1 -- No --> R3["HasRegistrationCore linear scan CanSatisfyServiceType"]
end
I --> R1
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
GFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.cs:56-66
**No-op `Register` paired with active assembly attribute creates an incomplete registry on full scan**
`Register` deliberately skips writing the handler so the benchmark can control lifetime explicitly — that is fine for the `RegisterGeneratedBenchmarkRegistry` path. However, the `[assembly: CqrsHandlerRegistryAttribute(typeof(GeneratedStreamLifetimeBenchmarkRegistry))]` attribute at the top of the file makes this registry discoverable by `RegisterCqrsHandlersFromAssembly`. On that path the invoker descriptor is registered but the handler is not, so any subsequent `CreateStream` / `SendAsync` dispatch would throw `InvalidOperationException("No CQRS request handler registered for …")`. Removing the assembly attribute — or adding a default-singleton fallback inside `Register` that can be overridden by the caller — would close the gap.
### Issue 2 of 3
GFramework.Core/Ioc/MicrosoftDiContainer.cs:1198-1201
**`FrozenServiceTypeIndex` stores mutable `HashSet<Type>` after construction**
The two `HashSet<T>` fields are only ever read after the constructor returns, but a mutable `HashSet` still holds extra capacity metadata and allows accidental mutation from within the same class. `System.Collections.Frozen.FrozenSet<T>` (available since .NET 8) is specifically designed for this pattern — built once, read many — and is typically faster for `Contains` lookups on the hot path that this index is meant to optimise.
```suggestion
private sealed class FrozenServiceTypeIndex(FrozenSet<Type> exactServiceTypes, FrozenSet<Type> openGenericServiceTypes)
{
private readonly FrozenSet<Type> _exactServiceTypes = exactServiceTypes;
private readonly FrozenSet<Type> _openGenericServiceTypes = openGenericServiceTypes;
```
### Issue 3 of 3
GFramework.Core/Ioc/MicrosoftDiContainer.cs:1212-1226
The two intermediate `HashSet<Type>` collections should be converted to `FrozenSet<Type>` before being passed to the constructor, so that the `Create` factory and the container fields are consistent.
```suggestion
var exactServiceTypes = new HashSet<Type>();
var openGenericServiceTypes = new HashSet<Type>();
foreach (var descriptor in descriptors)
{
var serviceType = descriptor.ServiceType;
exactServiceTypes.Add(serviceType);
if (serviceType.IsGenericTypeDefinition)
{
openGenericServiceTypes.Add(serviceType);
}
}
return new FrozenServiceTypeIndex(exactServiceTypes.ToFrozenSet(), openGenericServiceTypes.ToFrozenSet());
```
Reviews (3): Last reviewed commit: "fix(cqrs): 收口PR341剩余review尾项" | Re-trigger Greptile
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs (1)
99-101: 💤 Low value建议补充注释说明为何重新创建 runtime 实例
RegisterCqrsInfrastructure(由CreateFrozenGFrameworkContainer调用)已向容器内注册了一个ICqrsRuntime;这里又在容器冻结后创建了第二个实例并赋给_runtime。两者共享同一底层容器,功能上不冲突,但目的不同:容器内的 runtime 是为了让RegisterCqrsHandlersFromAssembly(...)能在配置阶段解析到 runtime 服务,而_runtime使用了包含 lifetime 参数的专属 logger 名称以区分不同生命周期矩阵的日志。若缺少这一说明,后续维护者可能会尝试改写为
container.GetRequired<ICqrsRuntime>(),导致 logger 名称退化为"CqrsDispatcher",使跨 lifetime 组的 benchmark 日志失去区分。📝 建议补充注释
+ // 容器内已由 RegisterCqrsInfrastructure 注册了一个 ICqrsRuntime(logger 名为 "CqrsDispatcher"), + // 此处额外创建一个携带 benchmark-specific logger 名称的独立实例,用于区分 Singleton / Transient 两档的运行日志。 + // 两个实例共享同一冻结容器,handler 解析路径完全一致,因此不存在功能上的干扰。 _runtime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime( _container, LoggerFactoryResolver.Provider.CreateLogger(nameof(StreamLifetimeBenchmarks) + "." + Lifetime));🤖 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/StreamLifetimeBenchmarks.cs` around lines 99 - 101, 在这段给 _runtime 赋值(GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(...))的代码附近补充注释,说明为何在容器冻结后还要重新创建一个 ICqrsRuntime 实例:RegisterCqrsInfrastructure(由 CreateFrozenGFrameworkContainer 调用)已经向容器注册了一个 runtime 用于 RegisterCqrsHandlersFromAssembly 在配置阶段解析,但这里单独创建的 _runtime 使用包含 Lifetime 的专属 logger 名称以在不同生命周期矩阵的基准测试日志中保持可区分性;并警告不要替换为 container.GetRequired<ICqrsRuntime>()(否则 logger 名称会退化为 "CqrsDispatcher" 并丢失区分)。
🤖 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 @.agents/skills/gframework-batch-boot/SKILL.md:
- Line 150: 修复 MD005 缩进错误:将文件 SKILL.md 中子项 "recompute the primary stop-condition
metric" 的缩进减少 1 个空格,使其与同级列表项对齐(与其他兄弟项采用相同的缩进级别),保存后重新运行 markdownlint
验证无需改动其他文本或内容。
In `@GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs`:
- Around line 60-66: Replace the direct casts to LegacyICqrsRuntime in
BenchmarkHostFactory with defensive type checks: instead of
(LegacyICqrsRuntime)runtime, verify runtime is LegacyICqrsRuntime using the "is
not" / pattern-match form and throw an InvalidOperationException containing both
the expected and actual runtime types if the check fails; register the matched
variable when successful. Do the same for the
container.GetRequired<ICqrsRuntime>() path: obtain the ICqrsRuntime, check it is
a LegacyICqrsRuntime before registering, and throw an InvalidOperationException
with full type info on mismatch; follow the same pattern used in
CqrsTestRuntime.cs (lines 102–111) for consistency.
---
Nitpick comments:
In `@GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs`:
- Around line 99-101: 在这段给 _runtime
赋值(GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(...))的代码附近补充注释,说明为何在容器冻结后还要重新创建一个
ICqrsRuntime 实例:RegisterCqrsInfrastructure(由 CreateFrozenGFrameworkContainer
调用)已经向容器注册了一个 runtime 用于 RegisterCqrsHandlersFromAssembly 在配置阶段解析,但这里单独创建的
_runtime 使用包含 Lifetime 的专属 logger 名称以在不同生命周期矩阵的基准测试日志中保持可区分性;并警告不要替换为
container.GetRequired<ICqrsRuntime>()(否则 logger 名称会退化为 "CqrsDispatcher" 并丢失区分)。
🪄 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: f4b7a5ab-cd9c-4df3-82ba-d6ef4707bd19
📒 Files selected for processing (16)
.agents/skills/gframework-batch-boot/SKILL.md.agents/skills/gframework-boot/SKILL.mdGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/README.mdGFramework.Cqrs/Internal/CqrsDispatcher.csai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.mdai-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: Analyze (C#)
- GitHub Check: Code Quality & Security
- GitHub Check: Build and Test
🧰 Additional context used
📓 Path-based instructions (8)
**/*.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.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.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.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/README.mdGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Core/Ioc/MicrosoftDiContainer.csai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.mdGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.csai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mdGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs
**/*.{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.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.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.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.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.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.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.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.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.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.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:
GFramework.Cqrs.Benchmarks/README.mdai-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.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs
🪛 LanguageTool
.agents/skills/gframework-boot/SKILL.md
[style] ~76-~76: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...re asking the user for clarification. - If the current turn already carries heavy ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🪛 markdownlint-cli2 (0.22.1)
.agents/skills/gframework-batch-boot/SKILL.md
[warning] 150-150: Inconsistent indentation for list items at the same level
Expected: 3; Actual: 4
(MD005, list-indent)
🔇 Additional comments (10)
GFramework.Core/Ioc/MicrosoftDiContainer.cs (1)
1053-1056: 冻结索引优化实现完整且一致。冻结后走索引查询、在
Clear/Dispose里回收索引,和当前锁模型、生命周期语义保持一致,改动方向很好。Also applies to: 1181-1182, 1191-1242
GFramework.Cqrs/Internal/CqrsDispatcher.cs (1)
108-108: 请求分发热路径精简得当。这里直接返回
ValueTask<TResponse>,在保持行为不变的前提下去掉了额外状态机开销,适合 benchmark/运行时热点路径。Also applies to: 125-126, 135-136
GFramework.Cqrs.Benchmarks/README.md (1)
18-18: 基准矩阵文案对齐良好。这些描述与当前 benchmark 的生成器/注册路径表述一致,可读性更好。
Also applies to: 21-22, 24-24, 34-34
GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs (1)
64-64: 缓存清理时机和兜底路径处理得很好。
Setup预清理 +Cleanup的try/finally组合能有效避免跨轮 benchmark 污染。Also applies to: 69-70, 94-101
GFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.cs (1)
72-73: pipeline 基准的处理器注册入口统一得很好。这里与其它 benchmark 的程序集注册路径保持一致,后续维护会更简单。
GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs (1)
21-22: 流式基准的注册与缓存隔离改动是正确的。程序集 registry 绑定与 setup/cleanup 缓存清理形成闭环,有助于减少跨轮次干扰。
Also applies to: 65-65, 70-70, 92-99
GFramework.Cqrs.Benchmarks/Messaging/GeneratedRequestPipelineBenchmarkRegistry.cs (1)
1-100: LGTM!手写 generated registry 模式实现一致;使用
nameof做反射方法名查找、?? throw防止静默失效,以及通过静态描述符列表缓存加速类型查找,都是正确做法。GFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultStreamingBenchmarkRegistry.cs (1)
1-96: LGTM!stream invoker 返回
object与框架的 invoker 合同一致(运行时负责向IAsyncEnumerable<TResponse>转型),nameof+?? throw的方法查找保护与其他 registry 保持对称。GFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.cs (1)
1-110: LGTM!
Register()刻意不写入 handler 生命周期(只记录 debug 日志)是正确设计:让 benchmark 主体通过RegisterGFrameworkHandler(container, Lifetime)显式控制Singleton / Transient变量,确保生命周期矩阵的比较变量保持单一。该意图在<remarks>中已清晰说明。GFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.cs (1)
1-100: LGTM!与
GeneratedRequestPipelineBenchmarkRegistry实现完全对称;ValueTask<BenchmarkResponse>返回类型、nameof反射查找、静态描述符缓存均正确,Register()按单例注册保持与原 steady-state 宿主一致的生命周期语义。
- 修复 benchmark 宿主误激活同程序集其他 generated registry 的接线路径,收窄服务索引与 descriptor 基线 - 恢复 CqrsDispatcher.SendAsync 的 faulted ValueTask 失败语义,并补充相关回归测试 - 补充 legacy runtime alias 的防守式类型检查、stream lifetime 注释与 cqrs-rewrite 恢复文档验证记录
Summary
Test ResultsDetails
Insights
Fail Rate
build-and-test: Run #1092
🎉 All tests passed!Slowest Tests
± Comparison with run #1091 at 5fac56a | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 39 runs. Github Test Reporter by CTRF 💚 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs (1)
78-95: ⚡ Quick win建议为缺失 handler 测试补充 pipeline behavior 的 mock 配置,减少对 dispatch 内部顺序的隐式依赖
当前测试使用
MockBehavior.Strict但只配置了Get返回null,未配置HasRegistration(IPipelineBehavior<...>)和GetAll(IPipelineBehavior<...>)。测试能通过,说明 dispatcher 当前会在检查 pipeline 之前先判断 handler 是否为null;一旦内部执行顺序调整,strict mock 会抛出MockException而非预期的InvalidOperationException,导致测试失败时的错误信息与实际意图不符,难以定位。♻️ 建议补充防御性 mock 配置
var runtime = CreateRuntime( container => { container .Setup(currentContainer => currentContainer.Get(typeof(IRequestHandler<ContextAwareRequest, int>))) .Returns((object?)null); + container + .Setup(currentContainer => currentContainer.HasRegistration(typeof(IPipelineBehavior<ContextAwareRequest, int>))) + .Returns(false); });🤖 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.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs` around lines 78 - 95, Test relies on MockBehavior.Strict but only stubs Get for IRequestHandler, making it brittle to internal ordering; update the mock setup in the CreateRuntime container configuration used by SendAsync(ContextAwareRequest) to also handle pipeline checks by configuring HasRegistration(typeof(IPipelineBehavior<ContextAwareRequest,int>)) to return false (or true as appropriate) and GetAll(typeof(IPipelineBehavior<ContextAwareRequest,int>)) to return an empty enumerable, so the strict mock won't throw if dispatcher queries pipeline registration/get-all before checking the handler and the test continues to assert the InvalidOperationException when handler is missing.
🤖 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/traces/cqrs-rewrite-migration-trace.md`:
- Around line 32-33: The "本轮下一步" section duplicates the already completed
"本轮权威验证" steps (Release build / targeted tests / license header check / `git
diff --check`), causing redundancy; locate the "本轮下一步" heading and either (a)
replace its content with true post-merge follow-ups (e.g., monitoring, rollout,
further integrations, follow-up issues) or (b) remove the duplicated lines
entirely so only "本轮权威验证" remains; target the text blocks containing the
headings "本轮下一步" and "本轮权威验证" to make this edit.
---
Nitpick comments:
In `@GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs`:
- Around line 78-95: Test relies on MockBehavior.Strict but only stubs Get for
IRequestHandler, making it brittle to internal ordering; update the mock setup
in the CreateRuntime container configuration used by
SendAsync(ContextAwareRequest) to also handle pipeline checks by configuring
HasRegistration(typeof(IPipelineBehavior<ContextAwareRequest,int>)) to return
false (or true as appropriate) and
GetAll(typeof(IPipelineBehavior<ContextAwareRequest,int>)) to return an empty
enumerable, so the strict mock won't throw if dispatcher queries pipeline
registration/get-all before checking the handler and the test continues to
assert the InvalidOperationException when handler is missing.
🪄 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: d647a06c-3aff-496e-a699-5c5fe100198a
📒 Files selected for processing (15)
.agents/skills/gframework-batch-boot/SKILL.mdGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Cqrs/Internal/CqrsHandlerRegistrar.csGFramework.Cqrs/Properties/AssemblyInfo.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 as they are similar to previous changes (7)
- GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs
- GFramework.Cqrs.Benchmarks/Messaging/RequestPipelineBenchmarks.cs
- GFramework.Cqrs/Internal/CqrsDispatcher.cs
- .agents/skills/gframework-batch-boot/SKILL.md
- GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs
- GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs
- ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
📜 Review details
🧰 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.Cqrs/Properties/AssemblyInfo.csGFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.csGFramework.Cqrs/Internal/CqrsHandlerRegistrar.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/Properties/AssemblyInfo.csGFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.csGFramework.Cqrs/Internal/CqrsHandlerRegistrar.csai-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/Properties/AssemblyInfo.csGFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.csGFramework.Cqrs/Internal/CqrsHandlerRegistrar.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/Properties/AssemblyInfo.csGFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.csGFramework.Cqrs/Internal/CqrsHandlerRegistrar.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/Properties/AssemblyInfo.csGFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.csGFramework.Cqrs/Internal/CqrsHandlerRegistrar.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/Properties/AssemblyInfo.csGFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.csGFramework.Cqrs/Internal/CqrsHandlerRegistrar.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/Properties/AssemblyInfo.csGFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.csGFramework.Cqrs/Internal/CqrsHandlerRegistrar.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.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.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.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/Properties/AssemblyInfo.csGFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.csGFramework.Cqrs/Internal/CqrsHandlerRegistrar.cs
🔇 Additional comments (6)
GFramework.Cqrs/Internal/CqrsHandlerRegistrar.cs (1)
82-99: 新增RegisterGeneratedRegistry入口实现简洁,LGTMnull 校验完备、IL 工厂缓存路径与现有
TryCreateGeneratedRegistry一致、collection expression[registry]在 net8.0+ 目标框架下合法。TryCreateGeneratedRegistry在各失败模式下已通过logger.Warn输出具体原因,最外层InvalidOperationException作为调用侧的编程时错误信号,设计合理。GFramework.Cqrs/Properties/AssemblyInfo.cs (1)
6-7:InternalsVisibleTo声明正确,LGTM两个友元程序集声明与 PR 中 benchmark/测试对
CqrsHandlerRegistrar内部成员的访问需求一致。程序集当前无强签名,因此无需附带公钥。若后续引入强签名,需同步补充PublicKey=...参数。GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs (1)
84-90: 定向 registry 接线正确,LGTM从全程序集扫描切到
RegisterGeneratedBenchmarkRegistry<GeneratedStreamInvokerBenchmarkRegistry>的改动与 PR 目标一致,确保基准容器不会意外激活同程序集内的其他 generated registry。GFramework.Cqrs.Benchmarks/Messaging/RequestInvokerBenchmarks.cs (1)
84-90: 与StreamInvokerBenchmarks的模式保持对称,LGTMGFramework.Cqrs.Tests/Cqrs/CqrsGeneratedRequestInvokerProviderTests.cs (1)
107-127: 隔离性验证测试设计完整,LGTM
Assert.Multiple同时断言 request provider 存在且 stream provider 为空,精确覆盖了RegisterGeneratedRegistry的"仅激活指定 registry、不旁触其他 registry"语义。[NonParallelizable]已在类级别声明,静态缓存的清理与恢复逻辑由现有SetUp/TearDown统一处理。GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs (1)
92-100:Cleanup的try/finally模式正确,LGTM即使
DisposeAll抛出,ClearDispatcherCaches仍会执行,避免 dispatcher 静态缓存残留污染后续 benchmark 轮次。与其他 benchmark 文件(如RequestInvokerBenchmarks)的清理模式对称。
- 修复 request faulted ValueTask 回归测试对 pipeline 探测顺序的隐式依赖,补齐 HasRegistration 与 GetAll 的防御性 mock - 更新 cqrs-rewrite tracking 与 trace,记录 PR #341 latest-head review 的 stale thread 复核结论与本轮验证结果
Summary
Test ResultsDetails
Insights
Fail Rate
build-and-test: Run #1093
🎉 All tests passed!Slowest Tests
± Comparison with run #1092 at fb96d5d | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 40 runs. Github Test Reporter by CTRF 💚 |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Summary by CodeRabbit
发行说明
新功能
性能优化
修复
文档