Feat/cqrs optimization#344
Conversation
- 补充 UseNotificationPublisher<TPublisher>() 的单例解析与重复注册回归覆盖 - 更新 notification publisher 组合根文档,说明实例重载与泛型重载的生命周期边界 - 更新 cqrs-rewrite 跟踪与追踪文档,记录 RP-119 的验证结果与下一恢复点
- 修复默认 CQRS runtime 在工厂层过早固化顺序 publisher 的问题 - 更新 dispatcher 与基础设施接线,确保组合根注册的 publisher 能在标准 publish 路径生效 - 补充 notification publisher 回归并更新 cqrs-rewrite 的 RP-120 恢复点
- 新增标准 Architecture 启动路径下自定义 notification publisher 的集成回归,验证 Configurator 注册的策略会被真实 publish 路径复用 - 更新 cqrs-rewrite active tracking 与 trace,推进恢复点到 RP-121 并记录当前验证结果与下一步边界
- 新增 dispatcher 实例级 request behavior presence cache,减少零管道请求 steady-state 的容器查询开销 - 补充 dispatcher cache 回归并更新 cqrs-rewrite active tracking 与 trace,记录 request benchmark 和 lifetime benchmark 结果
|
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (3)
📜 Recent 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)
🧰 Additional context used📓 Path-based instructions (8)**/Cqrs/**/*.cs📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.cs📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*[!.]*📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{cs,ts,tsx,js,jsx,py,sh}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{cs,ts,tsx,js,jsx,py}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{csproj,cs}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{cs,ts,tsx,js,jsx,py,sh,xml,csproj,props,targets}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{cs,ts,tsx,js,jsx,py,sh,xml}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (1)📚 Learning: 2026-04-06T12:45:43.921ZApplied to files:
🔇 Additional comments (3)
📝 WalkthroughWalkthroughPR 在 CqrsDispatcher 中引入实例级请求行为存在性缓存,支持通知发布器的延迟容器解析;工厂与运行时改为不预解析发布器;新增综合测试覆盖缓存隔离性与发布器接线;同步更新文档与迁移追踪。 ChangesCQRS 请求行为缓存与通知发布器延迟解析
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 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 |
|
| Filename | Overview |
|---|---|
| GFramework.Core/Services/Modules/CqrsRuntimeModule.cs | Removes premature container.Get() at registration time, fixing the root cause where custom publishers were invisible before container freeze. |
| GFramework.Cqrs/Internal/CqrsDispatcher.cs | Adds _resolvedNotificationPublisher instance field with Interlocked.CompareExchange-based lazy initialisation in ResolveNotificationPublisher(); correctly handles explicit-instance, container-resolved, and default-fallback paths without per-call allocation. |
| GFramework.Cqrs/CqrsRuntimeFactory.cs | Adds a no-publisher overload of CreateRuntime that delegates to the existing three-parameter overload with null, enabling callers to opt into deferred publisher resolution without ceremony. |
| GFramework.Tests.Common/CqrsTestRuntime.cs | RegisterInfrastructure now calls the new no-publisher overload of CreateRuntime, keeping test infrastructure consistent with the production module path and allowing pre-registered publishers to be picked up at first publish. |
| GFramework.Cqrs.Tests/Cqrs/CqrsNotificationPublisherTests.cs | New and updated tests cover explicit-publisher, container-resolved-publisher, and default-fallback paths; the strict mock setup for GetAll(INotificationPublisher) correctly mirrors the deferred resolution contract. |
| GFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.cs | New tests validate instance-registration, generic-type-registration, duplicate-registration guard, and end-to-end infrastructure reuse for both TaskWhenAll and Sequential publishers. |
| GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs | New integration test exercises the full architecture initialisation path with a custom publisher registered via Configurator, directly proving the CqrsRuntimeModule bug is resolved end-to-end. |
| GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.cs | Cache-test scaffolding updated with new state-reset helpers for the notification context; no logic concerns. |
Sequence Diagram
sequenceDiagram
participant Cfg as Architecture.Configurator
participant Mod as CqrsRuntimeModule.Register()
participant Dis as CqrsDispatcher
participant Con as IIocContainer (frozen)
Note over Cfg,Con: Architecture initialization
Cfg->>Con: Register(INotificationPublisher, CustomPublisher)
Mod->>Dis: new CqrsDispatcher(container, logger, null)
Note right of Dis: _notificationPublisher = null<br/>_resolvedNotificationPublisher = null
Mod->>Con: container.Freeze()
Note over Dis,Con: First PublishAsync call
Dis->>Dis: ResolveNotificationPublisher()
alt "_notificationPublisher != null"
Dis-->>Dis: return _notificationPublisher (explicit instance)
else "_resolvedNotificationPublisher != null"
Dis-->>Dis: return cached publisher (fast path)
else first call
Dis->>Con: container.GetAll(typeof(INotificationPublisher))
Con-->>Dis: [CustomPublisher]
Dis->>Dis: Interlocked.CompareExchange(ref _resolvedNotificationPublisher, CustomPublisher, null)
Dis-->>Dis: return _resolvedNotificationPublisher (CustomPublisher)
end
Dis->>Dis: publisher.PublishAsync(publishContext, cancellationToken)
Reviews (2): Last reviewed commit: "fix(cqrs): 收口PR344通知发布评审问题" | Re-trigger Greptile
Summary
Test ResultsDetails
Failed TestsCqrsNotificationPublisherTests Insights
Fail Rate
build-and-test: Run #1098
❌ Some tests failed!
Slowest Tests
± Comparison with run #1095 at 571c677 | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 43 runs. Github Test Reporter by CTRF 💚 |
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|
| dotnet-format | yes | 1 | no | 5.37s | ||
| ✅ REPOSITORY | gitleaks | yes | no | no | 8.72s | |
| ✅ REPOSITORY | trufflehog | yes | no | no | 6.56s |
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
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.cs (1)
645-663: ⚡ Quick win抽出共享的容器装配逻辑,避免隔离容器与夹具配置漂移。
CreateFrozenContainer()现在复制了SetUp()里的整套 CQRS 行为和 handler 注册。后续只要一边增删注册、另一边忘记同步,这个“实例级缓存隔离”回归就可能因为测试装配差异而误报或漏报。建议把这段注册提成一个共享 helper,让两个入口复用同一份容器形状。♻️ 建议的整理方式
+ private static void ConfigureDispatcherCacheFixture(MicrosoftDiContainer container) + { + container.RegisterCqrsPipelineBehavior<DispatcherPipelineCacheBehavior>(); + container.RegisterCqrsPipelineBehavior<DispatcherPipelineContextRefreshBehavior>(); + container.RegisterCqrsPipelineBehavior<DispatcherPipelineOrderOuterBehavior>(); + container.RegisterCqrsPipelineBehavior<DispatcherPipelineOrderInnerBehavior>(); + container.RegisterCqrsStreamPipelineBehavior<DispatcherStreamPipelineCacheBehavior>(); + container.RegisterCqrsStreamPipelineBehavior<DispatcherStreamPipelineContextRefreshBehavior>(); + container.RegisterCqrsStreamPipelineBehavior<DispatcherStreamPipelineOrderOuterBehavior>(); + container.RegisterCqrsStreamPipelineBehavior<DispatcherStreamPipelineOrderInnerBehavior>(); + + CqrsTestRuntime.RegisterHandlers( + container, + typeof(CqrsDispatcherCacheTests).Assembly, + typeof(ArchitectureContext).Assembly); + } + public void SetUp() { LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider(); _container = new MicrosoftDiContainer(); - _container.RegisterCqrsPipelineBehavior<DispatcherPipelineCacheBehavior>(); - _container.RegisterCqrsPipelineBehavior<DispatcherPipelineContextRefreshBehavior>(); - _container.RegisterCqrsPipelineBehavior<DispatcherPipelineOrderOuterBehavior>(); - _container.RegisterCqrsPipelineBehavior<DispatcherPipelineOrderInnerBehavior>(); - _container.RegisterCqrsStreamPipelineBehavior<DispatcherStreamPipelineCacheBehavior>(); - _container.RegisterCqrsStreamPipelineBehavior<DispatcherStreamPipelineContextRefreshBehavior>(); - _container.RegisterCqrsStreamPipelineBehavior<DispatcherStreamPipelineOrderOuterBehavior>(); - _container.RegisterCqrsStreamPipelineBehavior<DispatcherStreamPipelineOrderInnerBehavior>(); - - CqrsTestRuntime.RegisterHandlers( - _container, - typeof(CqrsDispatcherCacheTests).Assembly, - typeof(ArchitectureContext).Assembly); + ConfigureDispatcherCacheFixture(_container); _container.Freeze(); _context = new ArchitectureContext(_container); ... } private static MicrosoftDiContainer CreateFrozenContainer() { var container = new MicrosoftDiContainer(); - container.RegisterCqrsPipelineBehavior<DispatcherPipelineCacheBehavior>(); - ... - CqrsTestRuntime.RegisterHandlers( - container, - typeof(CqrsDispatcherCacheTests).Assembly, - typeof(ArchitectureContext).Assembly); + ConfigureDispatcherCacheFixture(container); container.Freeze(); return container; }🤖 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/CqrsDispatcherCacheTests.cs` around lines 645 - 663, Create a single shared helper that builds the CQRS container assembly used by both CreateFrozenContainer() and the test SetUp() to avoid drift: move the repeated RegisterCqrsPipelineBehavior/ RegisterCqrsStreamPipelineBehavior calls and the CqrsTestRuntime.RegisterHandlers(...) invocation into a new method (e.g., BuildCqrsContainerShape or ConfigureCqrsContainer) that returns or mutates a MicrosoftDiContainer, then call that helper from CreateFrozenContainer() and SetUp() before calling container.Freeze() so both places reuse the exact same registration shape.
🤖 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.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.cs`:
- Around line 109-113: Add an assertion that INotificationPublisher is
registered exactly once: after the existing checks (returnedContainer,
container.HasRegistration, and GetRequired assertions) assert that the container
contains exactly one registration for the INotificationPublisher service (for
example by verifying container.GetAll<INotificationPublisher>().Count() == 1 or
filtering container.Registrations by service type INotificationPublisher and
asserting Count == 1), while keeping the existing check that the resolved
instance is of type TrackingNotificationPublisher and resolves to the same
singleton instance.
In `@GFramework.Cqrs/Internal/CqrsDispatcher.cs`:
- Around line 242-249: Tests using a strict IIocContainer mock are failing
because ResolveNotificationPublisher() calls
container.GetAll(typeof(INotificationPublisher)) but the mock wasn't configured;
update the mocks in CqrsDispatcherContextValidationTests.cs and
CqrsNotificationPublisherTests.cs to setup
IIocContainer.GetAll(typeof(INotificationPublisher)) to return an empty
collection so ResolveNotificationPublisher() can fall back to
SequentialNotificationPublisher; target the IIocContainer mock setup for GetAll
to ensure PublishAsync calls don't throw.
---
Nitpick comments:
In `@GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.cs`:
- Around line 645-663: Create a single shared helper that builds the CQRS
container assembly used by both CreateFrozenContainer() and the test SetUp() to
avoid drift: move the repeated RegisterCqrsPipelineBehavior/
RegisterCqrsStreamPipelineBehavior calls and the
CqrsTestRuntime.RegisterHandlers(...) invocation into a new method (e.g.,
BuildCqrsContainerShape or ConfigureCqrsContainer) that returns or mutates a
MicrosoftDiContainer, then call that helper from CreateFrozenContainer() and
SetUp() before calling container.Freeze() so both places reuse the exact same
registration shape.
🪄 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: 1f718ae6-fad8-4b26-992f-d908ff7ceb98
📒 Files selected for processing (11)
GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Core/Services/Modules/CqrsRuntimeModule.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.csGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.csGFramework.Cqrs/CqrsRuntimeFactory.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Cqrs/README.mdGFramework.Tests.Common/CqrsTestRuntime.csai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.mdai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mddocs/zh-CN/core/cqrs.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (10)
**/*.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/CqrsRuntimeFactory.csGFramework.Core/Services/Modules/CqrsRuntimeModule.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Tests.Common/CqrsTestRuntime.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.csGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.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/CqrsRuntimeFactory.csGFramework.Core/Services/Modules/CqrsRuntimeModule.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Tests.Common/CqrsTestRuntime.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Cqrs/README.mddocs/zh-CN/core/cqrs.mdGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.csai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mdGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.csai-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 explainingwhyandwhen, not justwhat. Code should remain understandable without requiring external context
Avoid obvious comments such as// increment i
Files:
GFramework.Cqrs/CqrsRuntimeFactory.csGFramework.Core/Services/Modules/CqrsRuntimeModule.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Tests.Common/CqrsTestRuntime.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.csGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.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/CqrsRuntimeFactory.csGFramework.Core/Services/Modules/CqrsRuntimeModule.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Tests.Common/CqrsTestRuntime.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.csGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.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/CqrsRuntimeFactory.csGFramework.Core/Services/Modules/CqrsRuntimeModule.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Tests.Common/CqrsTestRuntime.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.csGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.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/CqrsRuntimeFactory.csGFramework.Core/Services/Modules/CqrsRuntimeModule.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Tests.Common/CqrsTestRuntime.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.csGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.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/CqrsRuntimeFactory.csGFramework.Core/Services/Modules/CqrsRuntimeModule.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Tests.Common/CqrsTestRuntime.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.csGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.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/README.mddocs/zh-CN/core/cqrs.mdai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mdai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.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/cqrs.md
**/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/CqrsDispatcherCacheTests.csGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.cs
🧠 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/CqrsRuntimeFactory.csGFramework.Core/Services/Modules/CqrsRuntimeModule.csGFramework.Cqrs/Internal/CqrsDispatcher.csGFramework.Tests.Common/CqrsTestRuntime.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.csGFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.cs
🪛 GitHub Actions: CI - Build & Test / Build and Test
GFramework.Cqrs/Internal/CqrsDispatcher.cs
[error] 242-242: Strict Moq exception during ResolveNotificationPublisher(): IIocContainer.GetAll(GFramework.Cqrs.Notification.INotificationPublisher) invocation failed with mock behavior Strict.
[error] 103-103: Strict Moq exception surfaced while calling CqrsDispatcher.PublishAsync(ICqrsContext, TNotification, CancellationToken).
🔇 Additional comments (11)
GFramework.Cqrs/README.md (1)
135-135: 文档更新准确反映了运行时行为。通知发布器策略表与示例代码正确区分了实例注册
UseNotificationPublisher(...)与泛型注册UseNotificationPublisher<TPublisher>()的语义,与CqrsDispatcher的延迟解析逻辑和CqrsRuntimeFactory的文档说明保持一致。Also applies to: 164-170
docs/zh-CN/core/cqrs.md (1)
128-128: LGTM!中文文档与英文 README 保持同步,准确描述了通知发布器的两种注册方式及其生命周期语义。
Also applies to: 163-169
ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md (1)
10-25: LGTM!迁移跟踪文档准确记录了 RP-122 的实现细节:dispatcher 实例级请求行为存在性缓存、benchmark 结果对比,以及验证脚本输出。文档清晰说明了缓存隔离性(按 dispatcher 实例)与性能收益。
Also applies to: 88-95, 169-191
GFramework.Cqrs/Internal/CqrsDispatcher.cs (2)
24-27: 实例级行为存在性缓存实现正确。
_requestBehaviorPresenceCache通过ConcurrentDictionary<Type, bool>按 behavior 服务类型缓存首次HasRegistration查询结果,有效减少零管道请求在稳态路径上的容器查询开销。文档清晰说明了缓存作用域(dispatcher 实例级)与线程安全性。Also applies to: 153-166
69-72: 延迟通知发布器解析逻辑符合预期。
ResolveNotificationPublisher()的优先级顺序清晰:显式实例 → 容器注册的单例 → 默认顺序发布器。文档准确说明了"容器冻结前创建 runtime 时无法提前拿到底层 provider 构造的实例"这一延迟解析的必要性。Also applies to: 227-250
GFramework.Cqrs/CqrsRuntimeFactory.cs (1)
27-30: LGTM!工厂方法的 XML 文档准确说明了
notificationPublisher参数为null时的解析优先级:优先复用容器中声明的INotificationPublisher,否则回退到默认顺序发布器。与CqrsDispatcher.ResolveNotificationPublisher()的实现逻辑一致。Also applies to: 44-47
GFramework.Core/Services/Modules/CqrsRuntimeModule.cs (1)
48-48: 运行时创建改为依赖延迟解析。
CqrsRuntimeModule.Register现在直接调用CreateRuntime(container, dispatcherLogger),不再提前解析INotificationPublisher。这符合 PR 目标,将发布器选择推迟到真正PublishAsync时,避免在容器冻结前提前固化策略。基于 AI summary,
GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs已新增集成测试InitializeAsync_Should_Reuse_Custom_NotificationPublisher_From_Configurator()验证标准启动路径复用自定义发布器。GFramework.Tests.Common/CqrsTestRuntime.cs (1)
67-67: LGTM!测试运行时创建路径与生产代码保持一致,同样改为延迟解析通知发布器。这确保测试环境能够真实反映生产行为。
GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs (3)
164-191: 新集成测试验证自定义发布器复用路径。
InitializeAsync_Should_Reuse_Custom_NotificationPublisher_From_Configurator()通过以下机制验证标准架构启动路径会复用Configurator中声明的自定义INotificationPublisher:
- 使用 Moq 创建包含 CQRS registry 元数据的模拟程序集
- 注册
ArchitectureTrackingNotificationPublisher与ArchitectureNotificationPublisherProbe- 发布通知后断言 probe 被调用且 handler 执行
测试结构清晰,覆盖了 PR 的核心场景。
Also applies to: 228-251, 287-348
33-33: 测试隔离:确保 SetUp 和 TearDown 对称重置。在
SetUp和TearDown中都调用AdditionalAssemblyNotificationHandlerState.Reset()是良好的测试隔离实践,确保测试间的静态状态不会互相污染。这与TrackingPipelineBehavior和LegacyBridgePipelineTracker的重置模式保持一致。Also applies to: 44-44
33-33: 所有引用的辅助类型均已正确定义。
AdditionalAssemblyNotificationHandlerState、AdditionalAssemblyNotification和AdditionalAssemblyNotificationHandlerRegistry已分别在GFramework.Core.Tests/Architectures/目录中以独立文件定义,无需任何改动。
- 修复 CqrsDispatcher 默认通知发布器热路径的重复解析与默认实例重复分配 - 补充 strict IIocContainer 测试装配与通知发布器唯一注册断言 - 重构 CqrsDispatcherCacheTests 共享容器装配并更新 cqrs-rewrite 恢复文档
Summary
Test ResultsDetails
Insights
Fail Rate
build-and-test: Run #1099
🎉 All tests passed!Slowest Tests
± Comparison with run #1098 at ddf878f | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 44 runs. Github Test Reporter by CTRF 💚 |
Summary by CodeRabbit
发布说明
Bug 修复
文档
测试