2323from time import clock
2424
2525from neo4j .addressing import SocketAddress , resolve
26- from neo4j .bolt import ConnectionPool , ServiceUnavailable , ProtocolError , DEFAULT_PORT , connect
26+ from neo4j .bolt import ConnectionPool , ServiceUnavailable , ProtocolError , DEFAULT_PORT , connect , ConnectionErrorHandler
2727from neo4j .compat .collections import MutableSet , OrderedDict
2828from neo4j .exceptions import CypherError , DatabaseUnavailableError , NotALeaderError , ForbiddenOnReadOnlyDatabaseError
2929from neo4j .util import ServerVersion
3232from neo4j .v1 .security import SecurityPlan
3333from neo4j .v1 .session import BoltSession
3434
35-
3635LOAD_BALANCING_STRATEGY_LEAST_CONNECTED = 0
3736LOAD_BALANCING_STRATEGY_ROUND_ROBIN = 1
3837LOAD_BALANCING_STRATEGY_DEFAULT = LOAD_BALANCING_STRATEGY_LEAST_CONNECTED
@@ -247,15 +246,26 @@ def _select(self, offset, addresses):
247246 return least_connected_address
248247
249248
249+ class RoutingConnectionErrorHandler (ConnectionErrorHandler ):
250+ """ Handler for errors in routing driver connections.
251+ """
252+
253+ def __init__ (self , pool ):
254+ super (RoutingConnectionErrorHandler , self ).__init__ ({
255+ SessionExpired : lambda address : pool .remove (address ),
256+ ServiceUnavailable : lambda address : pool .remove (address ),
257+ DatabaseUnavailableError : lambda address : pool .remove (address ),
258+ NotALeaderError : lambda address : pool .remove_writer (address ),
259+ ForbiddenOnReadOnlyDatabaseError : lambda address : pool .remove_writer (address )
260+ })
261+
262+
250263class RoutingConnectionPool (ConnectionPool ):
251264 """ Connection pool with routing table.
252265 """
253266
254- CLUSTER_MEMBER_FAILURE_ERRORS = (ServiceUnavailable , SessionExpired , DatabaseUnavailableError )
255- WRITE_FAILURE_ERRORS = (NotALeaderError , ForbiddenOnReadOnlyDatabaseError )
256-
257267 def __init__ (self , connector , initial_address , routing_context , * routers , ** config ):
258- super (RoutingConnectionPool , self ).__init__ (connector )
268+ super (RoutingConnectionPool , self ).__init__ (connector , RoutingConnectionErrorHandler ( self ) )
259269 self .initial_address = initial_address
260270 self .routing_context = routing_context
261271 self .routing_table = RoutingTable (routers )
@@ -402,21 +412,12 @@ def acquire(self, access_mode=None):
402412 try :
403413 connection = self .acquire_direct (address ) # should always be a resolved address
404414 connection .Error = SessionExpired
405- connection .error_handler = lambda error : self ._handle_connection_error (address , error )
406415 except ServiceUnavailable :
407416 self .remove (address )
408417 else :
409418 return connection
410419 raise SessionExpired ("Failed to obtain connection towards '%s' server." % access_mode )
411420
412- def _handle_connection_error (self , address , error ):
413- """ Handle routing connection send or receive error.
414- """
415- if isinstance (error , self .CLUSTER_MEMBER_FAILURE_ERRORS ):
416- self .remove (address )
417- elif isinstance (error , self .WRITE_FAILURE_ERRORS ):
418- self ._remove_writer (address )
419-
420421 def remove (self , address ):
421422 """ Remove an address from the connection pool, if present, closing
422423 all connections to that address. Also remove from the routing table.
@@ -428,7 +429,7 @@ def remove(self, address):
428429 self .routing_table .writers .discard (address )
429430 super (RoutingConnectionPool , self ).remove (address )
430431
431- def _remove_writer (self , address ):
432+ def remove_writer (self , address ):
432433 """ Remove a writer address from the routing table, if present.
433434 """
434435 self .routing_table .writers .discard (address )
@@ -450,8 +451,8 @@ def __init__(self, uri, **config):
450451 # scenario right now
451452 raise ValueError ("TRUST_ON_FIRST_USE is not compatible with routing" )
452453
453- def connector (a ):
454- return connect (a , security_plan .ssl_context , ** config )
454+ def connector (address , error_handler ):
455+ return connect (address , security_plan .ssl_context , error_handler , ** config )
455456
456457 pool = RoutingConnectionPool (connector , initial_address , routing_context , * resolve (initial_address ), ** config )
457458 try :
0 commit comments