48
48
using RabbitMQ . Client . Events ;
49
49
using RabbitMQ . Client . Exceptions ;
50
50
using RabbitMQ . Client . Impl ;
51
+
52
+ using RabbitMQ . Util ;
51
53
using RabbitMQ . Client . Logging ;
52
54
53
55
namespace RabbitMQ . Client . Framing . Impl
@@ -479,7 +481,6 @@ private void Init(IFrameHandler fh)
479
481
if ( ShouldTriggerConnectionRecovery ( args ) )
480
482
{
481
483
_recoveryLoopCommandQueue . Enqueue ( RecoveryCommand . BeginAutomaticRecovery ) ;
482
- _semaphore . Release ( ) ;
483
484
}
484
485
} ;
485
486
lock ( _eventLock )
@@ -963,8 +964,7 @@ private enum RecoveryConnectionState
963
964
private Task _recoveryTask ;
964
965
private RecoveryConnectionState _recoveryLoopState = RecoveryConnectionState . Connected ;
965
966
966
- private readonly ConcurrentQueue < RecoveryCommand > _recoveryLoopCommandQueue = new ConcurrentQueue < RecoveryCommand > ( ) ;
967
- private readonly SemaphoreSlim _semaphore = new SemaphoreSlim ( 0 ) ;
967
+ private readonly AsyncConcurrentQueue < RecoveryCommand > _recoveryLoopCommandQueue = new AsyncConcurrentQueue < RecoveryCommand > ( ) ;
968
968
private readonly CancellationTokenSource _recoveryCancellationToken = new CancellationTokenSource ( ) ;
969
969
private readonly TaskCompletionSource < int > _recoveryLoopComplete = new TaskCompletionSource < int > ( ) ;
970
970
@@ -977,29 +977,19 @@ private async Task MainRecoveryLoop()
977
977
{
978
978
while ( ! _recoveryCancellationToken . IsCancellationRequested )
979
979
{
980
- try
980
+ var command = await _recoveryLoopCommandQueue . DequeueAsync ( _recoveryCancellationToken . Token ) . ConfigureAwait ( false ) ;
981
+
982
+ switch ( _recoveryLoopState )
981
983
{
982
- await _semaphore . WaitAsync ( _recoveryCancellationToken . Token ) . ConfigureAwait ( false ) ;
983
- }
984
- catch ( TaskCanceledException )
985
- {
986
- // Swallowing the task cancellation in case we are stopping work.
987
- }
988
-
989
- if ( ! _recoveryCancellationToken . IsCancellationRequested && _recoveryLoopCommandQueue . TryDequeue ( out RecoveryCommand command ) )
990
- {
991
- switch ( _recoveryLoopState )
992
- {
993
- case RecoveryConnectionState . Connected :
994
- await RecoveryLoopConnectedHandler ( command ) . ConfigureAwait ( false ) ;
995
- break ;
996
- case RecoveryConnectionState . Recovering :
997
- await RecoveryLoopRecoveringHandler ( command ) . ConfigureAwait ( false ) ;
998
- break ;
999
- default :
1000
- ESLog . Warn ( "RecoveryLoop state is out of range." ) ;
1001
- break ;
1002
- }
984
+ case RecoveryConnectionState . Connected :
985
+ RecoveryLoopConnectedHandler ( command ) ;
986
+ break ;
987
+ case RecoveryConnectionState . Recovering :
988
+ RecoveryLoopRecoveringHandler ( command ) ;
989
+ break ;
990
+ default :
991
+ ESLog . Warn ( "RecoveryLoop state is out of range." ) ;
992
+ break ;
1003
993
}
1004
994
}
1005
995
}
@@ -1032,7 +1022,7 @@ private void StopRecoveryLoop()
1032
1022
/// Handles commands when in the Recovering state.
1033
1023
/// </summary>
1034
1024
/// <param name="command"></param>
1035
- private async Task RecoveryLoopRecoveringHandler ( RecoveryCommand command )
1025
+ private void RecoveryLoopRecoveringHandler ( RecoveryCommand command )
1036
1026
{
1037
1027
switch ( command )
1038
1028
{
@@ -1046,9 +1036,7 @@ private async Task RecoveryLoopRecoveringHandler(RecoveryCommand command)
1046
1036
}
1047
1037
else
1048
1038
{
1049
- await Task . Delay ( _factory . NetworkRecoveryInterval ) ;
1050
- _recoveryLoopCommandQueue . Enqueue ( RecoveryCommand . PerformAutomaticRecovery ) ;
1051
- _semaphore . Release ( ) ;
1039
+ ScheduleRecoveryRetry ( ) ;
1052
1040
}
1053
1041
1054
1042
break ;
@@ -1062,7 +1050,7 @@ private async Task RecoveryLoopRecoveringHandler(RecoveryCommand command)
1062
1050
/// Handles commands when in the Connected state.
1063
1051
/// </summary>
1064
1052
/// <param name="command"></param>
1065
- private async Task RecoveryLoopConnectedHandler ( RecoveryCommand command )
1053
+ private void RecoveryLoopConnectedHandler ( RecoveryCommand command )
1066
1054
{
1067
1055
switch ( command )
1068
1056
{
@@ -1071,14 +1059,24 @@ private async Task RecoveryLoopConnectedHandler(RecoveryCommand command)
1071
1059
break ;
1072
1060
case RecoveryCommand . BeginAutomaticRecovery :
1073
1061
_recoveryLoopState = RecoveryConnectionState . Recovering ;
1074
- await Task . Delay ( _factory . NetworkRecoveryInterval ) . ConfigureAwait ( false ) ;
1075
- _recoveryLoopCommandQueue . Enqueue ( RecoveryCommand . PerformAutomaticRecovery ) ;
1076
- _semaphore . Release ( ) ;
1062
+ ScheduleRecoveryRetry ( ) ;
1077
1063
break ;
1078
1064
default :
1079
1065
ESLog . Warn ( $ "RecoveryLoop command { command } is out of range.") ;
1080
1066
break ;
1081
1067
}
1082
1068
}
1069
+
1070
+ /// <summary>
1071
+ /// Schedule a background Task to signal the command queue when the retry duration has elapsed.
1072
+ /// </summary>
1073
+ private void ScheduleRecoveryRetry ( )
1074
+ {
1075
+ Task . Delay ( _factory . NetworkRecoveryInterval )
1076
+ . ContinueWith ( t =>
1077
+ {
1078
+ _recoveryLoopCommandQueue . Enqueue ( RecoveryCommand . PerformAutomaticRecovery ) ;
1079
+ } ) ;
1080
+ }
1083
1081
}
1084
1082
}
0 commit comments