58
58
)
59
59
from threading import (
60
60
Condition ,
61
- Lock ,
62
61
RLock ,
63
62
)
64
63
from time import perf_counter
@@ -875,7 +874,7 @@ def __init__(self, opener, pool_config, workspace_config, address):
875
874
log .debug ("[#0000] C: <NEO4J POOL> routing address %r" , address )
876
875
self .address = address
877
876
self .routing_tables = {workspace_config .database : RoutingTable (database = workspace_config .database , routers = [address ])}
878
- self .refresh_lock = Lock ()
877
+ self .refresh_lock = RLock ()
879
878
880
879
def __repr__ (self ):
881
880
""" The representation shows the initial routing addresses.
@@ -1109,23 +1108,25 @@ def _select_address(self, *, access_mode, database, bookmarks):
1109
1108
from neo4j .api import READ_ACCESS
1110
1109
""" Selects the address with the fewest in-use connections.
1111
1110
"""
1112
- self .create_routing_table (database )
1113
- self .ensure_routing_table_is_fresh (
1114
- access_mode = access_mode , database = database , bookmarks = bookmarks
1115
- )
1116
- log .debug ("[#0000] C: <ROUTING TABLE ENSURE FRESH> %r" , self .routing_tables )
1117
- if access_mode == READ_ACCESS :
1118
- addresses = self .routing_tables [database ].readers
1119
- else :
1120
- addresses = self .routing_tables [database ].writers
1121
- addresses_by_usage = {}
1122
- for address in addresses :
1123
- addresses_by_usage .setdefault (self .in_use_connection_count (address ), []).append (address )
1111
+ with self .refresh_lock :
1112
+ if access_mode == READ_ACCESS :
1113
+ addresses = self .routing_tables [database ].readers
1114
+ else :
1115
+ addresses = self .routing_tables [database ].writers
1116
+ addresses_by_usage = {}
1117
+ for address in addresses :
1118
+ addresses_by_usage .setdefault (
1119
+ self .in_use_connection_count (address ), []
1120
+ ).append (address )
1124
1121
if not addresses_by_usage :
1125
1122
if access_mode == READ_ACCESS :
1126
- raise ReadServiceUnavailable ("No read service currently available" )
1123
+ raise ReadServiceUnavailable (
1124
+ "No read service currently available"
1125
+ )
1127
1126
else :
1128
- raise WriteServiceUnavailable ("No write service currently available" )
1127
+ raise WriteServiceUnavailable (
1128
+ "No write service currently available"
1129
+ )
1129
1130
return choice (addresses_by_usage [min (addresses_by_usage )])
1130
1131
1131
1132
def acquire (self , access_mode = None , timeout = None , database = None ,
@@ -1137,17 +1138,24 @@ def acquire(self, access_mode=None, timeout=None, database=None,
1137
1138
1138
1139
from neo4j .api import check_access_mode
1139
1140
access_mode = check_access_mode (access_mode )
1141
+ with self .refresh_lock :
1142
+ self .create_routing_table (database )
1143
+ log .debug ("[#0000] C: <ROUTING TABLE ENSURE FRESH> %r" , self .routing_tables )
1144
+ self .ensure_routing_table_is_fresh (
1145
+ access_mode = access_mode , database = database , bookmarks = bookmarks
1146
+ )
1147
+
1140
1148
while True :
1141
1149
try :
1142
1150
# Get an address for a connection that have the fewest in-use connections.
1143
1151
address = self ._select_address (
1144
1152
access_mode = access_mode , database = database ,
1145
1153
bookmarks = bookmarks
1146
1154
)
1147
- log .debug ("[#0000] C: <ACQUIRE ADDRESS> database=%r address=%r" , database , address )
1148
1155
except (ReadServiceUnavailable , WriteServiceUnavailable ) as err :
1149
1156
raise SessionExpired ("Failed to obtain connection towards '%s' server." % access_mode ) from err
1150
1157
try :
1158
+ log .debug ("[#0000] C: <ACQUIRE ADDRESS> database=%r address=%r" , database , address )
1151
1159
connection = self ._acquire (address , timeout = timeout ) # should always be a resolved address
1152
1160
except ServiceUnavailable :
1153
1161
self .deactivate (address = address )
0 commit comments