27
27
28
28
from neo4j .bolt import ProtocolError , ServiceUnavailable
29
29
from neo4j .compat import urlparse
30
- from neo4j .exceptions import CypherError
30
+ from neo4j .exceptions import CypherError , TransientError
31
31
32
32
from .exceptions import DriverError , SessionError , SessionExpired , TransactionError
33
33
34
-
35
34
_warned_about_transaction_bookmarks = False
36
35
37
-
38
36
READ_ACCESS = "READ"
39
37
WRITE_ACCESS = "WRITE"
40
38
@@ -53,7 +51,6 @@ def retry_delay_generator(initial_delay, multiplier, jitter_factor):
53
51
54
52
55
53
class ValueSystem (object ):
56
-
57
54
def hydrate (self , values ):
58
55
""" Hydrate values from raw representations into client objects.
59
56
"""
@@ -435,6 +432,11 @@ def _run_transaction(self, access_mode, unit_of_work, *args, **kwargs):
435
432
return unit_of_work (tx , * args , ** kwargs )
436
433
except (ServiceUnavailable , SessionExpired ) as error :
437
434
last_error = error
435
+ except TransientError as error :
436
+ if is_retriable_transientError (error ):
437
+ last_error = error
438
+ else :
439
+ raise error
438
440
sleep (next (retry_delay ))
439
441
t1 = clock ()
440
442
raise last_error
@@ -461,6 +463,17 @@ def __bookmark__(self, result):
461
463
pass
462
464
463
465
466
+ def is_retriable_transientError (error ):
467
+ """
468
+ :type error: TransientError
469
+ """
470
+ if (error .code != "Neo.TransientError.Transaction.Terminated"
471
+ and error .code != "Neo.TransientError.Transaction.LockClientStopped" ):
472
+ return True
473
+ else :
474
+ return False
475
+
476
+
464
477
class Transaction (object ):
465
478
""" Container for multiple Cypher queries to be executed within
466
479
a single context. Transactions can be used within a :py:const:`with`
0 commit comments