File tree Expand file tree Collapse file tree 3 files changed +20
-9
lines changed
src/MongoDB.Driver.Core/Core/Servers
tests/MongoDB.Driver.Core.Tests/Core/Servers Expand file tree Collapse file tree 3 files changed +20
-9
lines changed Original file line number Diff line number Diff line change @@ -84,8 +84,6 @@ public void Dispose()
8484
8585 public async Task RunAsync ( )
8686 {
87- await Task . Yield ( ) ; // return control immediately
88-
8987 while ( ! _cancellationToken . IsCancellationRequested )
9088 {
9189 try
Original file line number Diff line number Diff line change @@ -128,7 +128,14 @@ public void Initialize()
128128 {
129129 if ( _state . TryChange ( State . Initial , State . Open ) )
130130 {
131- _ = MonitorServerAsync ( ) . ConfigureAwait ( false ) ;
131+ // the call to Task.Factory.StartNew is not normally recommended or necessary
132+ // we are using it temporarily to work around a race condition in some of our tests
133+ // the issue is that we set up some mocked async methods to return results immediately synchronously
134+ // which results in the MonitorServerAsync method making more progress synchronously than the test expected
135+ // by using Task.Factory.StartNew we introduce a short delay before the MonitorServerAsync Task starts executing
136+ // the delay is whatever time it takes for the new Task to be activated and scheduled
137+ // and the delay is usually long enough for the test to get past the race condition (though not guaranteed)
138+ _ = Task . Factory . StartNew ( ( ) => _ = MonitorServerAsync ( ) . ConfigureAwait ( false ) ) . ConfigureAwait ( false ) ;
132139 _ = _roundTripTimeMonitor . RunAsync ( ) . ConfigureAwait ( false ) ;
133140 }
134141 }
@@ -189,8 +196,6 @@ private async Task<IConnection> InitializeConnectionAsync(CancellationToken canc
189196
190197 private async Task MonitorServerAsync ( )
191198 {
192- await Task . Yield ( ) ; // return control immediately
193-
194199 var metronome = new Metronome ( _serverMonitorSettings . HeartbeatInterval ) ;
195200 var monitorCancellationToken = _monitorCancellationTokenSource . Token ;
196201
Original file line number Diff line number Diff line change 1414*/
1515
1616using System ;
17+ using System . Diagnostics ;
1718using System . Threading ;
1819using System . Threading . Tasks ;
1920using FluentAssertions ;
@@ -38,13 +39,20 @@ public void Dispose_can_be_called_multiple_times()
3839 public void RequestHeartbeat_should_respect_to_minHeartbeatInterval ( [ Values ( 10 , - 1 ) ] int heartbeatIntervalInMinutes )
3940 {
4041 var heartbeatInterval = heartbeatIntervalInMinutes == - 1 ? Timeout . InfiniteTimeSpan : TimeSpan . FromMinutes ( heartbeatIntervalInMinutes ) ;
41- var subject = new HeartbeatDelay ( heartbeatInterval , TimeSpan . FromSeconds ( 2 ) ) ;
42+ var minHeartbeatInterval = TimeSpan . FromSeconds ( 2 ) ;
4243
44+ var stopwatch = Stopwatch . StartNew ( ) ;
45+ var subject = new HeartbeatDelay ( heartbeatInterval , minHeartbeatInterval ) ;
4346 subject . RequestHeartbeat ( ) ;
47+ var timeout = TimeSpan . FromMinutes ( 1 ) ;
48+ var result = Task . WaitAny ( subject . Task , Task . Delay ( timeout ) ) ;
49+ if ( result != 0 )
50+ {
51+ throw new Exception ( $ "The test timeout { timeout } is exceeded.") ;
52+ }
53+ stopwatch . Stop ( ) ;
4454
45- SpinWait . SpinUntil ( ( ) => subject . Task . Status != TaskStatus . WaitingForActivation , TimeSpan . FromMilliseconds ( 1500 ) ) . Should ( ) . BeFalse ( ) ;
46- Thread . Sleep ( TimeSpan . FromMilliseconds ( 700 ) ) ;
47- subject . Task . Status . Should ( ) . Be ( TaskStatus . RanToCompletion ) ;
55+ stopwatch . Elapsed . Should ( ) . BeGreaterOrEqualTo ( minHeartbeatInterval - TimeSpan . FromMilliseconds ( 15 ) ) ;
4856 }
4957
5058 [ Fact ]
You can’t perform that action at this time.
0 commit comments