@@ -47,15 +47,16 @@ public static TResult Execute<TResult>(OperationContext operationContext, IRetry
4747 operationContext . ThrowIfTimedOutOrCanceled ( ) ;
4848
4949 ServerDescription server = null ;
50+ var exceptionFromChannelAcquisition = false ;
5051 try
5152 {
5253 context . AcquireOrReplaceChannel ( operationContext , deprioritizedServers ) ;
5354 ChannelPinningHelper . PinChannellIfRequired ( context . ChannelSource , context . Channel , context . Binding . Session ) ;
5455 server = context . ChannelSource . ServerDescription ;
5556
57+ operationAttempts ++ ;
5658 transactionNumber ??= AreRetriesAllowed ( operation . WriteConcern , context , context . ChannelSource . ServerDescription ) ? context . Binding . Session . AdvanceTransactionNumber ( ) : null ;
5759
58- operationAttempts ++ ;
5960 var operationResult = operation . ExecuteAttempt ( operationContext , context , operationAttempts , transactionNumber ) ;
6061 var tokensToDeposit = RetryabilityHelper . OperationRetryBackpressureConstants . RetryTokenReturnRate ;
6162 if ( attempt > 1 )
@@ -74,9 +75,14 @@ public static TResult Execute<TResult>(OperationContext operationContext, IRetry
7475 }
7576 catch ( Exception ex )
7677 {
78+ if ( server == null )
79+ {
80+ exceptionFromChannelAcquisition = true ;
81+ }
82+
7783 originalException ??= ex ;
7884
79- if ( ! ShouldRetry ( operationContext , operation . WriteConcern , context , tokenBucket , ex , attempt , context . Random , out var backoff ) )
85+ if ( ! ShouldRetry ( operationContext , operation . WriteConcern , context , tokenBucket , ex , attempt , context . Random , exceptionFromChannelAcquisition , out var backoff ) )
8086 {
8187 throw originalException ;
8288 }
@@ -114,6 +120,7 @@ public static async Task<TResult> ExecuteAsync<TResult>(OperationContext operati
114120 operationContext . ThrowIfTimedOutOrCanceled ( ) ;
115121
116122 ServerDescription server = null ;
123+ var exceptionFromChannelAcquisition = false ;
117124 try
118125 {
119126 //TODO This seems to be idempotent
@@ -146,9 +153,14 @@ public static async Task<TResult> ExecuteAsync<TResult>(OperationContext operati
146153 }
147154 catch ( Exception ex )
148155 {
156+ if ( server == null )
157+ {
158+ exceptionFromChannelAcquisition = true ;
159+ }
160+
149161 originalException ??= ex ;
150162
151- if ( ! ShouldRetry ( operationContext , operation . WriteConcern , context , tokenBucket , ex , attempt , context . Random , out var backoff ) )
163+ if ( ! ShouldRetry ( operationContext , operation . WriteConcern , context , tokenBucket , ex , attempt , context . Random , exceptionFromChannelAcquisition , out var backoff ) )
152164 {
153165 throw originalException ;
154166 }
@@ -172,16 +184,25 @@ private static bool ShouldRetry(OperationContext operationContext,
172184 Exception exception ,
173185 int attempt ,
174186 IRandom random ,
187+ bool exceptionFromChannelAcquisition ,
175188 out TimeSpan backoff )
176189 {
177190 backoff = TimeSpan . Zero ;
178191
179- exception = exception is MongoAuthenticationException mongoAuthenticationException ? mongoAuthenticationException . InnerException : exception ;
192+ bool isRetryableRead ;
193+ if ( exceptionFromChannelAcquisition )
194+ {
195+ //Exceptions from channel acquisition could be wrapped in a MongoAuthenticationException, in which case we need to look at the inner exception to decide if it's retryable or not
196+ var exceptionToAnalyze = exception is MongoAuthenticationException mongoAuthenticationException ? mongoAuthenticationException . InnerException : exception ;
180197
181- var isRetryableReadException = RetryabilityHelper . IsRetryableReadException ( exception ) ;
182- var isRetryableRead = context . RetryRequested && ! context . Binding . Session . IsInTransaction && isRetryableReadException ;
198+ var isRetryableReadException = RetryabilityHelper . IsRetryableReadException ( exceptionToAnalyze ) ;
199+ isRetryableRead = context . RetryRequested && ! context . Binding . Session . IsInTransaction && isRetryableReadException ;
200+ }
201+ else
202+ {
203+ isRetryableRead = false ;
204+ }
183205
184- //TODO We can shortcircuit this
185206 var isRetryableWriteException = RetryabilityHelper . IsRetryableWriteException ( exception ) ;
186207 var isRetryableWrites = AreRetriesAllowed ( writeConcern , context , context . ChannelSource . ServerDescription ) && isRetryableWriteException ;
187208
0 commit comments