Skip to content

Commit 3482e6a

Browse files
4.0 multi database (#384)
* removed redundant imports * implemented get routing table call for bolt 4.0 * moved neo4j driver test to an explicit neo4j driver test file * refactor renamed cx.server to cx.server_info * whitespace fix * implemented driver.supports_multi_db function * summary.protocol_version is now in summary.server.protocol_version * updated the success data to be like the actual data sent * added variable database to summary information * access mode fix and specifying database is implemented through config settings access mode is fixed and tested properly * added comments about routing * rotuing tables are updated per database includes new tests, code improvements and some minor fixes. * fixed test against Neo4j 3.4 * added comment about circular dependency for Bolt subclass * resolved pr comments * fixed begin_transaction function api
1 parent f9d15f9 commit 3482e6a

File tree

89 files changed

+1128
-374
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+1128
-374
lines changed

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ Argument Renaming Changes
154154
* :code:`Transaction.run(statement, ...` is now :code:`Transaction.run(query, ...`
155155
* :code:`StatementResultSummary.statement` is now :code:`ResultSummary.query`
156156
* :code:`StatementResultSummary.statement_type` is now :code:`ResultSummary.query_type`
157+
* :code:`StatementResultSummary.protocol_version` is now :code:`ResultSummary.server.protocol_version`
157158

158159

159160
Dependency Changes

docs/source/usage_patterns.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,6 @@ Transaction Object Work Pattern
266266
267267
query = Query("RETURN 1 AS x, timeout=10, metadata={"hello": 123})
268268
269-
tx = session.begin_transaction(bookmark=None, metadata=None, timeout=None)
269+
tx = session.begin_transaction(metadata=None, timeout=None)
270270
tx.run(query)
271271
tx.commit()

neo4j/__init__.py

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,6 @@ def driver(cls, uri, *, auth=None, **config):
134134
URI_SCHEME_NEO4J_SELF_SIGNED_CERTIFICATE,
135135
URI_SCHEME_NEO4J_SECURE,
136136
)
137-
from neo4j.conf import (
138-
TRUST_ALL_CERTIFICATES,
139-
TRUST_SYSTEM_CA_SIGNED_CERTIFICATES
140-
)
141137

142138
driver_type, security_type, parsed = parse_neo4j_uri(uri)
143139

@@ -252,8 +248,7 @@ def parse_targets(cls, *targets):
252248
targets = " ".join(targets)
253249
if not targets:
254250
targets = cls.default_targets
255-
addresses = Address.parse_list(targets, default_host=cls.default_host,
256-
default_port=cls.default_port)
251+
addresses = Address.parse_list(targets, default_host=cls.default_host, default_port=cls.default_port)
257252
return addresses
258253

259254

@@ -314,6 +309,26 @@ def verify_connectivity(self, **config):
314309
"""
315310
raise NotImplementedError
316311

312+
@experimental("Feature support query, based on Bolt Protocol Version and Neo4j Server Version will change in the future.")
313+
def supports_multi_db(self):
314+
""" Check if the server or cluster supports multi-databases.
315+
316+
:return: Returns true if the server or cluster the driver connects to supports multi-databases, otherwise false.
317+
:rtype: bool
318+
"""
319+
from neo4j.io._bolt4x0 import Bolt4x0
320+
321+
multi_database = False
322+
cx = self._pool.acquire(access_mode=READ_ACCESS, timeout=self._pool.workspace_config.connection_acquisition_timeout, database=self._pool.workspace_config.database)
323+
324+
# TODO: This logic should be inside the Bolt subclasses, because it can change depending on Bolt Protocol Version.
325+
if cx.PROTOCOL_VERSION >= Bolt4x0.PROTOCOL_VERSION and cx.server_info.version_info() >= Version(4, 0, 0):
326+
multi_database = True
327+
328+
self._pool.release(cx)
329+
330+
return multi_database
331+
317332

318333
class BoltDriver(Direct, Driver):
319334
""" A :class:`.BoltDriver` is created from a ``bolt`` URI and addresses
@@ -326,10 +341,18 @@ class BoltDriver(Direct, Driver):
326341

327342
@classmethod
328343
def open(cls, target, *, auth=None, **config):
344+
"""
345+
:param target:
346+
:param auth:
347+
:param config: The values that can be specified are found in :class: `neo4j.PoolConfig` and :class: `neo4j.WorkspaceConfig`
348+
349+
:return:
350+
:rtype: :class: `neo4j.BoltDriver`
351+
"""
329352
from neo4j.io import BoltPool
330353
address = cls.parse_target(target)
331354
pool_config, default_workspace_config = Config.consume_chain(config, PoolConfig, WorkspaceConfig)
332-
pool = BoltPool.open(address, auth=auth, **pool_config)
355+
pool = BoltPool.open(address, auth=auth, pool_config=pool_config, workspace_config=default_workspace_config)
333356
return cls(pool, default_workspace_config)
334357

335358
def __init__(self, pool, default_workspace_config):
@@ -338,6 +361,12 @@ def __init__(self, pool, default_workspace_config):
338361
self._default_workspace_config = default_workspace_config
339362

340363
def session(self, **config):
364+
"""
365+
:param config: The values that can be specified are found in :class: `neo4j.SessionConfig`
366+
367+
:return:
368+
:rtype: :class: `neo4j.Session`
369+
"""
341370
from neo4j.work.simple import Session
342371
session_config = SessionConfig(self._default_workspace_config, config)
343372
SessionConfig.consume(config) # Consume the config
@@ -372,16 +401,15 @@ def open(cls, *targets, auth=None, routing_context=None, **config):
372401
from neo4j.io import Neo4jPool
373402
addresses = cls.parse_targets(*targets)
374403
pool_config, default_workspace_config = Config.consume_chain(config, PoolConfig, WorkspaceConfig)
375-
pool = Neo4jPool.open(*addresses, auth=auth, routing_context=routing_context, **pool_config)
404+
pool = Neo4jPool.open(*addresses, auth=auth, routing_context=routing_context, pool_config=pool_config, workspace_config=default_workspace_config)
376405
return cls(pool, default_workspace_config)
377406

378407
def __init__(self, pool, default_workspace_config):
379-
Routing.__init__(self, pool.routing_table.initial_routers)
408+
Routing.__init__(self, pool.get_default_database_initial_router_addresses())
380409
Driver.__init__(self, pool)
381410
self._default_workspace_config = default_workspace_config
382411

383412
def session(self, **config):
384-
from neo4j.work.simple import Session
385413
session_config = SessionConfig(self._default_workspace_config, config)
386414
SessionConfig.consume(config) # Consume the config
387415
return Session(self._pool, session_config)
@@ -392,9 +420,6 @@ def pipeline(self, **config):
392420
PipelineConfig.consume(config) # Consume the config
393421
return Pipeline(self._pool, pipeline_config)
394422

395-
def get_routing_table(self):
396-
return self._pool.routing_table
397-
398423
def verify_connectivity(self, **config):
399424
"""
400425
:raise ServiceUnavailable: raised if the server does not support routing or if routing support is broken.
@@ -406,11 +431,11 @@ def _verify_routing_connectivity(self):
406431
from neo4j.exceptions import ServiceUnavailable
407432
from neo4j._exceptions import BoltHandshakeError
408433

409-
table = self.get_routing_table()
434+
table = self._pool.get_routing_table_for_default_database()
410435
routing_info = {}
411436
for ix in list(table.routers):
412437
try:
413-
routing_info[ix] = self._pool.fetch_routing_info(table.routers[0])
438+
routing_info[ix] = self._pool.fetch_routing_info(address=table.routers[0], timeout=self._default_workspace_config.connection_acquisition_timeout, database=self._default_workspace_config.database)
414439
except BoltHandshakeError as error:
415440
routing_info[ix] = None
416441

neo4j/api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
TRUST_ALL_CERTIFICATES = "TRUST_ALL_CERTIFICATES"
5454

5555
SYSTEM_DATABASE = "system"
56-
DEFAULT_DATABASE = None
56+
DEFAULT_DATABASE = None # Must be a non string hashable value
5757

5858

5959
class Auth:

neo4j/conf.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,14 +304,15 @@ class SessionConfig(WorkspaceConfig):
304304
#: Bookmarks
305305
bookmarks = ()
306306

307-
# Default AccessMode
307+
#: Default AccessMode
308308
default_access_mode = WRITE_ACCESS
309309
# access_mode = DeprecatedAlias("default_access_mode")
310310

311311

312312
class TransactionConfig(Config):
313-
""" Transaction configuration.
313+
""" Transaction configuration. This is internal for now.
314314
315+
neo4j.session.begin_transaction
315316
neo4j.Query
316317
neo4j.unit_of_work
317318
@@ -322,3 +323,18 @@ class TransactionConfig(Config):
322323

323324
#: Timeout
324325
timeout = None # seconds
326+
327+
328+
class RoutingConfig(Config):
329+
""" Neo4jDriver routing settings. This is internal for now.
330+
"""
331+
332+
#: Routing Table Purge_Delay
333+
routing_table_purge_delay = 30.0 # seconds
334+
# The TTL + routing_table_purge_delay should be used to check if the database routing table should be removed.
335+
336+
#: Max Routing Failures
337+
# max_routing_failures = 1
338+
339+
#: Retry Timeout Delay
340+
# retry_timeout_delay = 5.0 # seconds

0 commit comments

Comments
 (0)