Repository navigation
test: deflake stale-reader grace test (release on dedicated thread, not ThreadPool timer) - #578
Conversation
StreamMessageConsumerStallingReaderTests.Start_WhenStoppedReaderExitsWithinGrace_WaitsAndRestartsSameInstance scheduled the stream release via a System.Threading.Timer callback, which runs on the shared ThreadPool. Under CI load that queue can be starved past its 200ms due time, occasionally blowing the consumer's 1000ms grace join and failing the test with ConsumerThreadNotExitedException even though production behavior was correct. Releasing from a dedicated background thread instead avoids ThreadPool queuing delay. Confirmed by inspecting a prior CI failure (run 32580100693) that reproduced exactly this symptom with no intervening code change before the next run passed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
/agentic_review |
PR Summary by QodoDeflake stale-reader grace test by releasing on a dedicated thread
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
Code Review by Qodo
1.
|
Qodo round 1 on #578: the prior fix ignored releaser.Join()'s result, so if the background thread were ever still alive when the test's `using var stream` disposes, a late Release() call could throw ObjectDisposedException on that background thread — process-terminating rather than a clean test failure. Assert the join succeeds instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit de94fe0 |
Qodo round 2 on #578: removing the try/finally in the previous fix reintroduced the exact problem it was meant to guard against — if consumer.Start() throws, the releaser join is skipped entirely and the using-block disposals can run while the background thread is still pending, risking an ObjectDisposedException on that thread. Restore the join in a finally block, but check its result afterward rather than asserting inside finally, so a genuine exception from Start() is never masked by the join assertion. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit d3bdc82 |
|
Qodo-clean, CI green — ready for review. |
Flaky-test-fixer routine: CI history (
gh run list) showedStreamMessageConsumerStallingReaderTests.Start_WhenStoppedReaderExitsWithinGrace_WaitsAndRestartsSameInstancefail on net9.0 withConsumerThreadNotExitedException, then pass on the next run with only an unrelated commit (a different test file) in between — a genuine flake, not a real regression.What was wrong: the test scheduled the stream release via a
System.Threading.Timercallback due 200ms afterStart()begins its 1000ms grace-period wait.Timercallbacks run on the shared .NET ThreadPool, and under CI load — many test classes executing in parallel — that queue can occasionally be starved well past the 200ms due time, blowing the 1000ms grace window and failing the test even though the productionStart()/grace-join logic was working correctly. This was a test-timing issue, not a bug inStreamMessageConsumer.How it was fixed: the release now runs on its own dedicated background
ThreadwithThread.Sleep(200)instead of aThreadPool-queuedTimer, so it isn't subject to pool contention from other running tests.This is a test-only change — no production code touched, so it's safe by construction (same assertions, same timing budget, just a more reliable trigger for the release).
Verified: the affected test run 5x back-to-back (all green), full
dotnet testsuite green on net9.0 and net10.0 (3729 total, 0 failed, 2 skipped, both TFMs). No bench validation needed (test-only change).Not merging — for review.