Feat/cqrs optimization#347
Conversation
- 新增 FirstItem 与 DrainAll 两种 stream 观测模式,补齐 steady-state StreamingBenchmarks 的参数矩阵。 - 重构 stream 消费路径为共享 helper,分别覆盖首元素观测与完整枚举基线。
- 新增 StreamInvokerBenchmarks 的 FirstItem 与 DrainAll 双观测口径,并补齐相关 XML 注释。 - 引入 ScopedBenchmarkContainer 与 scoped request helper,为 RequestLifetimeBenchmarks 建立真实作用域边界下的 Scoped 生命周期矩阵。 - 更新 cqrs-rewrite 的 active tracking 与 trace,记录 RP-129 的多 worker 波次、串行化 smoke 验证与新的恢复入口。
- 新增真实 scoped stream benchmark helper,确保作用域覆盖完整枚举周期 - 扩展 StreamLifetimeBenchmarks 到 Singleton、Scoped、Transient 全矩阵并记录 scoped 结果 - 更新 benchmark README 与 cqrs-rewrite 恢复文档,收口当前验证结论与下一批方向
- 新增 benchmark 入口 artifacts suffix 解析与独立 host 工作目录重启逻辑 - 更新 benchmark README 并发运行约定,补充隔离命令示例 - 更新 cqrs-rewrite 恢复文档,记录并发验证结果与后续恢复点
|
Warning Rate limit exceeded
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 We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (10)
📝 Walkthrough走查此PR为GFramework.Cqrs基准测试框架引入真正的请求级作用域生命周期支持,并实现基于命令行选项的并发运行自动隔离机制。通过新增作用域dispatch助手、容器适配器、流观察模式拆分、程序入口隔离逻辑,完整支持单机多进程并发基准执行。 变更基准测试框架作用域隔离与并发支持
预估代码审查工作量🎯 4 (复杂) | ⏱️ ~45 分钟 可能相关的PR
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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.Cqrs.Benchmarks/Messaging/ScopedBenchmarkContainer.cs | New 515-line adapter that wraps the frozen root container and routes Get/GetAll to an explicitly-created per-call IServiceScope; mutation methods throw; CreateScope() delegates to the scoped provider (not the root), which is a subtle semantic inconsistency if the runtime calls it internally. |
| GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs | Adds four scoped dispatch helpers and two private async iterators; scope lifecycle is correctly managed with using-based ScopeLease / IServiceScope. |
| GFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs | Extends lifetime matrix to Scoped; creates ScopedBenchmarkContainer and scoped runtime only for the Scoped variant; GlobalCleanup disposes _container and _serviceProvider but omits explicit disposal of _scopedContainer. |
| GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs | Extends stream lifetime matrix to Scoped; refactors Setup into focused private methods; GlobalCleanup similarly omits explicit disposal of _scopedReflectionContainer and _scopedGeneratedContainer. |
| GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs | Adds FirstItem/DrainAll StreamObservation param and refactors benchmark methods to share ConsumeFirstItemAsync/DrainAsync helpers; no scoped lifetime changes. |
| GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs | Mirrors StreamInvokerBenchmarks: adds FirstItem/DrainAll observation mode, extracts ConsumeFirstItemAsync/DrainAsync helpers, no issues found. |
| GFramework.Cqrs.Benchmarks/Program.cs | Adds --artifacts-suffix isolated host mechanism; ValidateIsolatedHostDirectory correctly guards against nesting but uses OrdinalIgnoreCase which is inconsistent with Path.GetRelativePath on Linux. |
Prompt To Fix All With AI
Fix the following 4 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 4
GFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs:143
`_scopedContainer` is created in `Setup()` when `Lifetime == HandlerLifetime.Scoped` but is not included in the `DisposeAll` call here. `ScopedBenchmarkContainer` implements `IDisposable`, so if an unhandled exception were to leave `_activeScope` non-null (e.g., a benchmark iteration threw before the `using` block disposed the `ScopeLease`), that scope would not be released at cleanup. Adding it to `DisposeAll` is the safest pattern to follow consistently with how the root containers are managed.
```suggestion
BenchmarkCleanupHelper.DisposeAll(_container, _serviceProvider, _scopedContainer);
```
### Issue 2 of 4
GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs:140
`_scopedReflectionContainer` and `_scopedGeneratedContainer` are both `ScopedBenchmarkContainer` instances created when `Lifetime == HandlerLifetime.Scoped`, but neither is passed to `DisposeAll`. The same reasoning as in `RequestLifetimeBenchmarks` applies: if a benchmark iteration leaves an active scope open (e.g., via an uncaught exception), `Cleanup` will dispose the root containers without releasing the child scope held inside the adapters.
```suggestion
BenchmarkCleanupHelper.DisposeAll(_reflectionContainer, _generatedContainer, _serviceProvider, _scopedReflectionContainer, _scopedGeneratedContainer);
```
### Issue 3 of 4
GFramework.Cqrs.Benchmarks/Messaging/ScopedBenchmarkContainer.cs:403-406
**`CreateScope()` returns a child of the active scope, not of the root**
When called while a scope is active, this delegates to `GetScopedProvider().CreateScope()`, which produces a nested scope rather than a fresh root-level scope. If the CQRS runtime ever calls `container.CreateScope()` internally during `SendAsync` or `CreateStream` (e.g., for pipeline behaviors that manage their own scope), those pipeline scopes become grandchildren of the benchmark-managed scope and could add invisible allocation overhead to the `Scoped` matrix rows.
### Issue 4 of 4
GFramework.Cqrs.Benchmarks/Program.cs:232-246
**Case-insensitive equality check is wrong on Linux**
The normalized path equality uses `StringComparison.OrdinalIgnoreCase`, which is correct on Windows but incorrect on Linux (case-sensitive filesystems). On Linux, `/tmp/Output` and `/tmp/output` are distinct directories; the guard would incorrectly report them as the same and throw. `Path.GetRelativePath` (used just below for the nesting check) uses `StringComparison.Ordinal` on Linux, making the two checks inconsistent on that platform.
Reviews (2): Last reviewed commit: "fix(cqrs): 修复 benchmark scoped 宿主与 PR 恢复..." | Re-trigger Greptile
Summary
Test ResultsDetails
Insights
Fail Rate
build-and-test: Run #1104
🎉 All tests passed!Slowest Tests
± Comparison with run #1101 at 654bda9 | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 47 runs. Github Test Reporter by CTRF 💚 |
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|
| dotnet-format | yes | 1 | no | 5.36s | ||
| ✅ REPOSITORY | gitleaks | yes | no | no | 8.52s | |
| ✅ REPOSITORY | trufflehog | yes | no | no | 7.05s |
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: 6
🤖 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 159-185: The "最近权威验证" section in
cqrs-rewrite-migration-tracking.md has accumulated repeated historical
verification lines and should be trimmed: move older benchmark/run/check entries
into a new archive file under ai-plan/public/archive (e.g.,
ai-plan/public/archive/cqrs-rewrite-migration-history.md), leaving only the
minimal current recovery point (the latest successful build/run summary) and the
immediate next steps in the active todos file; update the active file's "最近权威验证"
to reference the archive (link or short note) and remove redundant lines, and
ensure any referenced filenames like GFramework.Cqrs.Benchmarks/* remain in the
archive entries so the provenance is preserved.
- Around line 10-13: Summary: The markdown still uses a placeholder for the "当前
PR 锚点" instead of the real PR; replace it with the actual PR and keep tracking
accurate. Fix: edit the cqrs-rewrite-migration-tracking.md entry that contains
the field "当前 PR 锚点" and change its value from "待重新抓取" to the actual PR
reference "PR `#347`"; ensure the recovery point identifier `CQRS-REWRITE-RP-131`
and the phase `Phase 8` remain correct and that future updates to this file
always record the completed work, validation results, and the next recovery
point rather than placeholders.
In `@ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`:
- Around line 3-91: The active trace file
ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md is growing
into an append-only changelog; trim it to only the current stage summary (e.g.
the "2026-05-11" header's key decision points, recent validations, and immediate
next steps) and move older, detailed phase-by-phase entries (the long "阶段:"
sections and per-benchmark validations) into ai-plan/public/archive/...; ensure
the top-level file keeps concise headings and a pointer/link to the new archive
files so reviewers can still find full history.
In `@GFramework.Cqrs.Benchmarks/Messaging/ScopedBenchmarkContainer.cs`:
- Around line 45-337: Add full XML documentation to all public members of
ScopedBenchmarkContainer (e.g., RegisterSingleton<T>,
RegisterSingleton<TService,TImpl>, RegisterTransient, RegisterScoped,
RegisterPlurality, RegisterSystem, Register, RegisterFactory,
RegisterCqrsPipelineBehavior, RegisterCqrsStreamPipelineBehavior,
RegisterCqrsHandlersFromAssembly(s), ExecuteServicesHook, Get<T>/Get(Type),
GetRequired<T>/GetRequired(Type), GetAll<T>/GetAll(Type), GetAllSorted<T>,
GetAllByPriority<T>/GetAllByPriority(Type), HasRegistration, Contains<T>,
ContainsInstance, Clear, Freeze, GetServicesUnsafe, CreateScope, SetContext,
GetContext, Dispose and CreateMutationNotSupportedException) by adding
appropriate /// <summary/> plus <param name="..."/>, <returns/>, and <exception
cref="..."/> tags where relevant (for example methods that throw
CreateMutationNotSupportedException should document the
InvalidOperationException), and use <remarks/> for any behavioral notes
(readonly scope semantics, delegation to _rootContainer/_scopedProvider). Ensure
signatures in the XML match generic/type parameter names and document null
argument checks (ArgumentNullException) for methods that validate inputs
(Get(Type), GetRequired(Type), GetAll(Type), HasRegistration(Type), etc.).
In `@GFramework.Cqrs.Benchmarks/Program.cs`:
- Around line 32-42: ParseInvocation currently only sets
invocation.ArtifactsSuffix from the CLI, so host isolation check using
invocation.ArtifactsSuffix misses cases where the suffix comes from the
environment (ResolveArtifactsPath). Modify ParseInvocation to also compute and
expose a boolean (e.g., Invocation.ShouldIsolateHost or
Invocation.ArtifactsSuffixEffective) that is true when an artifacts suffix is in
effect from either the command line or the
GFRAMEWORK_CQRS_BENCHMARK_ARTIFACTS_SUFFIX env var; then replace checks that
read invocation.ArtifactsSuffix (the RunFromIsolatedHost decision at the shown
block and the other sites around the 97-98 and 169-179 regions) to use the new
boolean so environment-provided suffixes trigger RunFromIsolatedHost and
consistent isolation behavior with ResolveArtifactsPath.
- Around line 109-116: 在调用 PrepareIsolatedHostDirectory
前加入检查以拒绝目标目录等于或位于源目录内部的配置:验证 artifactsPath / isolatedHostDirectory 与
sourceHostDirectory(AppContext.BaseDirectory)之间的路径关系,若 isolatedHostDirectory ==
sourceHostDirectory 或 isolatedHostDirectory 是 sourceHostDirectory 的子路径,则抛出
ArgumentException(或 ArgumentNullException 的合适替代)并给出清晰错误信息;在所有相关调用位置(包括上面片段用到的
variables artifactsPath、sourceHostDirectory、isolatedHostDirectory、以及文件中另一个相似片段
220-245)都应用相同校验以防止递归拷贝导致的 host/host/... 膨胀。
🪄 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: 14740b50-2795-4ce9-8df5-52738a07455c
📒 Files selected for processing (10)
GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/ScopedBenchmarkContainer.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Program.csGFramework.Cqrs.Benchmarks/README.mdai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.mdai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
**/*.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 (///)
XML documentation comments MUST use<summary>,<param>,<returns>,<exception>, and<remarks>where applicable, explaining intent, contract, and usage constraints instead of restating syntax
If a member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly in XML documentation
Add inline comments for non-trivial logic, concurrency or threading behavior, performance-sensitive paths, workarounds and compatibility constraints, edge cases, registration order, lifecycle sequencing, and generated code assumptions
Avoid obvious comments such as// increment i
Methods with non-trivial logic MUST document: The core idea, Key decisions, and Edge case handling, if any
Comments MUST NOT be trivial, redundant, or misleading. Prefer explainingwhyandwhen, not justwhat. Code should remain understandable without requiring external context. Prefer slightly more explanation over too little for framework code
Do not rely on implicit imports. Declare every requiredusingexplicitly
Write null-safe code that respects nullable annotations instead of suppressing warnings by default
Use the namespace patternGFramework.{Module}.{Feature}with PascalCase segments
Follow standard C# naming: Types, methods, properties, events, and constants use PascalCase; Interfaces useIprefix; Parameters and locals use camelCase; Private fields use_camelCase
Use 4 spaces for indentation. Do not use tabs
Use Allman braces
Keepusingdirectives at the top...
Files:
GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.csGFramework.Cqrs.Benchmarks/Program.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/ScopedBenchmarkContainer.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs
**/README.md
📄 CodeRabbit inference engine (AGENTS.md)
**/README.md: Use the canonical filenameREADME.md. Do not introduce newReadMe.mdor other filename variants
A module README MUST describe: the module's purpose, the relationship to adjacent runtime, abstractions, or generator packages, the major subdirectories or subsystems the reader is expected to use, the minimum adoption path, and the correspondingdocs/zh-CN/entry points
If a module's responsibilities, setup, public API surface, generator inputs, or adoption path change, update that module'sREADME.mdin the same change
Files:
GFramework.Cqrs.Benchmarks/README.md
ai-plan/public/**
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/public/**: Contributors MUST keep committedai-plan/public/**content safe to publish in Git history
Active tracking and trace files are recovery entrypoints, not append-only changelogs. They MUST stay concise enough forbootto locate the current recovery point quickly
When completed and validated stages begin to accumulate, contributors MUST archive their detailed history out of the activetodos/andtraces/entry files in the same change. Keep only the current recovery point, active facts, active risks, immediate next step, and pointers to the relevant archive files in the default boot path
When a topic is fully complete, move the entire topic directory underai-plan/public/archive/<topic>/and remove it fromai-plan/public/README.mdin the same change
When a task spans multiple commits or is likely to exceed a single agent context window, update both the recovery document and the trace at each meaningful milestone before pausing or handing work off
If subagents are used on a complex task, the main agent MUST capture the delegated scope and any accepted findings in the active recovery document or trace before continuing implementation
Files:
ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mdai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
ai-plan/**
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/**: Never write secrets, tokens, credentials, private keys, machine usernames, home-directory paths, hostnames, IP addresses, proprietary URLs, or other sensitive environment details into anyai-plan/**file
Never record absolute file-system paths inai-plan/**; use repository-relative paths, branch names, PR numbers, or stable document identifiers instead
Files:
ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.mdai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
ai-plan/public/**/traces/**
📄 CodeRabbit inference engine (AGENTS.md)
Contributors MUST maintain a matching execution trace under
ai-plan/public/<topic>/traces/for complex work. The trace should record the current date, key decisions, validation milestones, and the immediate next step
Files:
ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
ai-plan/public/**/todos/**
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/public/**/todos/**: When working from a tracked implementation plan, contributors MUST update the corresponding tracking document underai-plan/public/<topic>/todos/in the same change
Tracking updates MUST reflect completed work, newly discovered issues, validation results, and the next recommended recovery point
For any multi-step refactor, migration, or cross-module task, contributors MUST create or adopt a dedicated recovery document underai-plan/public/<topic>/todos/before making substantive code changes
Recovery documents MUST record the current phase, the active recovery point identifier, known risks, and the next recommended resume step so another contributor or subagent can continue the work safely
Files:
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.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.csGFramework.Cqrs.Benchmarks/Program.csGFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.csGFramework.Cqrs.Benchmarks/Messaging/ScopedBenchmarkContainer.csGFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.csGFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs
🔇 Additional comments (7)
GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs (2)
178-219: request 级作用域边界处理得对。每次发送都新建 scope,并在 scope 内解析 runtime / mediator,能避免
Scopedhandler 退化成根容器解析,这和这组 benchmark 的建模目标是一致的。
222-273: 异步流的作用域生命周期处理正确。把
using var scope放进 async iterator 里是这里的关键点:无论是完整 drain、提前break还是异常退出,最终都会走到同一处释放逻辑,Scoped依赖不会在建流后被提前销毁。Also applies to: 309-350
GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs (1)
161-218: 观测模式拆分与消费路径抽取实现清晰
ObserveAsync+ConsumeFirstItemAsync/DrainAsync的分层让“首元素成本”和“全量枚举成本”边界非常明确,benchmark 可读性和可比性都更好。GFramework.Cqrs.Benchmarks/Messaging/RequestLifetimeBenchmarks.cs (1)
157-185: Scoped 与非 Scoped 分发路径划分合理
Lifetime == Scoped时切换到BenchmarkHostFactory的显式作用域 helper,非 Scoped 保持预建 runtime/mediator 直连,这个分流实现和 benchmark 语义一致。GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs (1)
204-267: Scoped stream 路径与观测消费路径衔接正确在
Scoped模式下通过CreateScopedGFrameworkStream/CreateScopedMediatRStream建流,再统一走ObserveAsync消费,作用域边界与观测口径都保持一致。GFramework.Cqrs.Benchmarks/README.md (1)
59-74: 并发运行约束与用法示例更新到位
--artifacts-suffix的并发隔离约定写得足够清楚,且和当前 benchmark 入口行为一致,能有效减少并发 smoke 的使用歧义。GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs (1)
189-247:ObserveAsync抽象让 invoker 观测维度更可比把首元素消费和全量消费统一收敛到共享 helper 后,四组 benchmark 方法的行为对齐更直接,后续读数解释成本更低。
- 修复 benchmark 入口的 artifacts 隔离判断与嵌套宿主目录保护,避免并发运行时宿主目录递归膨胀 - 优化 request 与 stream 生命周期 benchmark 的 scoped 宿主模型,复用单个 runtime 并仅在每次调用时创建真实 DI scope - 补充 ScopedBenchmarkContainer 的 XML 合同说明,并收敛 README 与 ai-plan active 入口到当前 PR 恢复点
Summary
Test ResultsDetails
Insights
Fail Rate
build-and-test: Run #1106
🎉 All tests passed!Slowest Tests
± Comparison with run #1104 at c50fd59 | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 48 runs. Github Test Reporter by CTRF 💚 |
Summary by CodeRabbit
发布说明
新功能
--artifacts-suffix并发运行基准测试,自动隔离输出目录文档