fix(transactions): await recovery cleanup tasks - #11188
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
ProducerCancellationScope.DisposeAsync can throw if the producer faults, potentially masking the original test failure during await using cleanup.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Lite
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
src/Orleans.Transactions.TestKit.Base/TestRunners/TransactionRecoveryTestsRunner.cs — ProducerCancellationScope.DisposeAsync currently awaits producer directly. If producer… |
What changed in this PR
This PR tightens task and cancellation lifetime management in TransactionRecoveryTestsRunner to ensure recovery scenarios don’t outlive fixture-owned resources, aligning the test kit with CA2025 guidance and preventing cleanup races during transaction recovery tests.
Changes:
- Made producer shutdown/cleanup explicitly async-owned by the runner (cancel + await producer before disposing its token source).
- Ensured participant cleanup observation and silo shutdown tasks are cancelled/awaited so gates/fixtures aren’t disposed while work is still running.
- Added focused lifetime-ordering tests and enabled CA2025 warnings for
Orleans.Transactions.TestKit.Base.
| File | Description |
|---|---|
| test/Transactions/Orleans.Transactions.Tests/TransactionRecoveryTestsRunnerLifetimeTests.cs | Adds deterministic tests covering producer cancellation-scope disposal ordering and phase-gate observation lifetime. |
| src/Orleans.Transactions.TestKit.Base/TestRunners/TransactionRecoveryTestsRunner.cs | Refactors recovery runner cleanup to cancel/await owned tasks (producer, cleanup observation, shutdown) and introduces async disposal scope. |
| .editorconfig | Enables CA2025 warnings for Orleans.Transactions.TestKit.Base sources. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
c48a035 to
4e075db
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The new lifetime test CreateTransition() mixes named and positional arguments in a way that will not compile.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Lite
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
test/Transactions/Orleans.Transactions.Tests/TransactionRecoveryTestsRunnerLifetimeTests.cs — CreateTransition() mixes named and positional arguments in the RecoveryTransition constructor… |
Issues resolved since last review (1)
| Severity | Finding |
|---|---|
src/Orleans.Transactions.TestKit.Base/TestRunners/TransactionRecoveryTestsRunner.cs — ProducerCancellationScope.DisposeAsync currently awaits producer directly. If producer… View resolved comment |
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The new timeout cleanup path can mask the original TimeoutException if the shutdown task faults, which can make failures misleading.
Review tier: Lite
Findings: None
Issues resolved since last review (1)
| Severity | Finding |
|---|---|
test/Transactions/Orleans.Transactions.Tests/TransactionRecoveryTestsRunnerLifetimeTests.cs — CreateTransition() mixes named and positional arguments in the RecoveryTransition constructor… View resolved comment |
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/Orleans.Transactions.TestKit.Base/TestRunners/TransactionRecoveryTestsRunner.cs:326
- In the TimeoutException handler,
await shutdown; throw;can mask the original timeout ifshutdownfaults (the await will throw instead of rethrowing the timeout). If the intent is to ensure shutdown completes for lifetime reasons but still report the timeout as the primary failure, suppress exceptions from the shutdown task in this path.


Problem
Transaction recovery tests could let participant observation, silo shutdown, or transaction production continue after the resources they use became eligible for disposal. Enabling CA2025 for the complete
Orleans.Transactions.TestKit.Baseproject exposed three lifetime paths inTransactionRecoveryTestsRunner.Solution
Orleans.Transactions.TestKit.Base.Rationale
The recovery runner now owns every spawned operation through completion. Cancellation stops new work while the current operation settles, phase gates retain the disposal behavior established in #11167, and primary recovery failures retain precedence over a concurrent cleanup watchdog timeout. Two narrow CA2025 suppressions document guarantees the analyzer cannot follow across the structured cleanup paths: each task is awaited before the fixture or gate can dispose its resources.
Microsoft Reviewers: Open in CodeFlow