@@ -2009,6 +2009,7 @@ async def _retry_internal(
20092009 read_pref : Optional [_ServerMode ] = None ,
20102010 retryable : bool = False ,
20112011 operation_id : Optional [int ] = None ,
2012+ is_run_command : bool = False ,
20122013 ) -> T :
20132014 """Internal retryable helper for all client transactions.
20142015
@@ -2020,6 +2021,7 @@ async def _retry_internal(
20202021 :param address: Server Address, defaults to None
20212022 :param read_pref: Topology of read operation, defaults to None
20222023 :param retryable: If the operation should be retried once, defaults to None
2024+ :param is_run_command: If this is a runCommand operation, defaults to False
20232025
20242026 :return: Output of the calling func()
20252027 """
@@ -2034,6 +2036,7 @@ async def _retry_internal(
20342036 address = address ,
20352037 retryable = retryable ,
20362038 operation_id = operation_id ,
2039+ is_run_command = is_run_command ,
20372040 ).run ()
20382041
20392042 async def _retryable_read (
@@ -2045,6 +2048,7 @@ async def _retryable_read(
20452048 address : Optional [_Address ] = None ,
20462049 retryable : bool = True ,
20472050 operation_id : Optional [int ] = None ,
2051+ is_run_command : bool = False ,
20482052 ) -> T :
20492053 """Execute an operation with consecutive retries if possible
20502054
@@ -2060,6 +2064,7 @@ async def _retryable_read(
20602064 :param address: Optional address when sending a message, defaults to None
20612065 :param retryable: if we should attempt retries
20622066 (may not always be supported even if supplied), defaults to False
2067+ :param is_run_command: If this is a runCommand operation, defaults to False.
20632068 """
20642069
20652070 # Ensure that the client supports retrying on reads and there is no session in
@@ -2078,6 +2083,7 @@ async def _retryable_read(
20782083 read_pref = read_pref ,
20792084 retryable = retryable ,
20802085 operation_id = operation_id ,
2086+ is_run_command = is_run_command ,
20812087 )
20822088
20832089 async def _retryable_write (
@@ -2747,6 +2753,7 @@ def __init__(
27472753 address : Optional [_Address ] = None ,
27482754 retryable : bool = False ,
27492755 operation_id : Optional [int ] = None ,
2756+ is_run_command : bool = False ,
27502757 ):
27512758 self ._last_error : Optional [Exception ] = None
27522759 self ._retrying = False
@@ -2769,6 +2776,7 @@ def __init__(
27692776 self ._operation = operation
27702777 self ._operation_id = operation_id
27712778 self ._attempt_number = 0
2779+ self ._is_run_command = is_run_command
27722780
27732781 async def run (self ) -> T :
27742782 """Runs the supplied func() and attempts a retry
@@ -2809,18 +2817,27 @@ async def run(self) -> T:
28092817 always_retryable = False
28102818 overloaded = False
28112819 exc_to_check = exc
2820+
2821+ if self ._is_run_command and not (
2822+ self ._client .options .retry_reads and self ._client .options .retry_writes
2823+ ):
2824+ raise
28122825 # Execute specialized catch on read
28132826 if self ._is_read :
28142827 if isinstance (exc , (ConnectionFailure , OperationFailure )):
28152828 # ConnectionFailures do not supply a code property
28162829 exc_code = getattr (exc , "code" , None )
28172830 overloaded = exc .has_error_label ("SystemOverloadedError" )
28182831 always_retryable = exc .has_error_label ("RetryableError" ) and overloaded
2819- if not always_retryable and (
2820- self ._is_not_eligible_for_retry ()
2821- or (
2822- isinstance (exc , OperationFailure )
2823- and exc_code not in helpers_shared ._RETRYABLE_ERROR_CODES
2832+ if (
2833+ not self ._client .options .retry_reads
2834+ or not always_retryable
2835+ and (
2836+ self ._is_not_eligible_for_retry ()
2837+ or (
2838+ isinstance (exc , OperationFailure )
2839+ and exc_code not in helpers_shared ._RETRYABLE_ERROR_CODES
2840+ )
28242841 )
28252842 ):
28262843 raise
@@ -2851,7 +2868,11 @@ async def run(self) -> T:
28512868 retryable_write_label = exc_to_check .has_error_label ("RetryableWriteError" )
28522869 overloaded = exc_to_check .has_error_label ("SystemOverloadedError" )
28532870 always_retryable = exc_to_check .has_error_label ("RetryableError" ) and overloaded
2854- if not self ._retryable and not always_retryable :
2871+ if (
2872+ not self ._client .options .retry_writes
2873+ or not self ._retryable
2874+ and not always_retryable
2875+ ):
28552876 raise
28562877 if retryable_write_label or always_retryable :
28572878 assert self ._session
0 commit comments