2424
2525# pylint: disable=ungrouped-imports
2626from google .cloud .exceptions import NotFound
27+ from google .cloud .exceptions import GrpcRendezvous
2728from google .cloud .spanner ._helpers import _options_with_prefix
2829from google .cloud .spanner .batch import Batch
2930from google .cloud .spanner .snapshot import Snapshot
@@ -286,7 +287,7 @@ def run_in_transaction(self, func, *args, **kw):
286287 txn .begin ()
287288 try :
288289 return_value = func (txn , * args , ** kw )
289- except GaxError as exc :
290+ except ( GaxError , GrpcRendezvous ) as exc :
290291 _delay_until_retry (exc , deadline )
291292 del self ._transaction
292293 continue
@@ -318,15 +319,20 @@ def _delay_until_retry(exc, deadline):
318319 :type deadline: float
319320 :param deadline: maximum timestamp to continue retrying the transaction.
320321 """
321- if exc_to_code (exc .cause ) != StatusCode .ABORTED :
322+ if isinstance (exc , GrpcRendezvous ): # pragma: NO COVER see #3663
323+ cause = exc
324+ else :
325+ cause = exc .cause
326+
327+ if exc_to_code (cause ) != StatusCode .ABORTED :
322328 raise
323329
324330 now = time .time ()
325331
326332 if now >= deadline :
327333 raise
328334
329- delay = _get_retry_delay (exc )
335+ delay = _get_retry_delay (cause )
330336 if delay is not None :
331337
332338 if now + delay > deadline :
@@ -336,7 +342,7 @@ def _delay_until_retry(exc, deadline):
336342# pylint: enable=misplaced-bare-raise
337343
338344
339- def _get_retry_delay (exc ):
345+ def _get_retry_delay (cause ):
340346 """Helper for :func:`_delay_until_retry`.
341347
342348 :type exc: :class:`google.gax.errors.GaxError`
@@ -345,7 +351,7 @@ def _get_retry_delay(exc):
345351 :rtype: float
346352 :returns: seconds to wait before retrying the transaction.
347353 """
348- metadata = dict (exc . cause .trailing_metadata ())
354+ metadata = dict (cause .trailing_metadata ())
349355 retry_info_pb = metadata .get ('google.rpc.retryinfo-bin' )
350356 if retry_info_pb is not None :
351357 retry_info = RetryInfo ()
0 commit comments