Skip to content

4.0 multi database #384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ Argument Renaming Changes
* :code:`Transaction.run(statement, ...` is now :code:`Transaction.run(query, ...`
* :code:`StatementResultSummary.statement` is now :code:`ResultSummary.query`
* :code:`StatementResultSummary.statement_type` is now :code:`ResultSummary.query_type`
* :code:`StatementResultSummary.protocol_version` is now :code:`ResultSummary.server.protocol_version`


Dependency Changes
Expand Down
2 changes: 1 addition & 1 deletion docs/source/usage_patterns.rst
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,6 @@ Transaction Object Work Pattern

query = Query("RETURN 1 AS x, timeout=10, metadata={"hello": 123})

tx = session.begin_transaction(bookmark=None, metadata=None, timeout=None)
tx = session.begin_transaction(metadata=None, timeout=None)
tx.run(query)
tx.commit()
55 changes: 40 additions & 15 deletions neo4j/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,6 @@ def driver(cls, uri, *, auth=None, **config):
URI_SCHEME_NEO4J_SELF_SIGNED_CERTIFICATE,
URI_SCHEME_NEO4J_SECURE,
)
from neo4j.conf import (
TRUST_ALL_CERTIFICATES,
TRUST_SYSTEM_CA_SIGNED_CERTIFICATES
)

driver_type, security_type, parsed = parse_neo4j_uri(uri)

Expand Down Expand Up @@ -252,8 +248,7 @@ def parse_targets(cls, *targets):
targets = " ".join(targets)
if not targets:
targets = cls.default_targets
addresses = Address.parse_list(targets, default_host=cls.default_host,
default_port=cls.default_port)
addresses = Address.parse_list(targets, default_host=cls.default_host, default_port=cls.default_port)
return addresses


Expand Down Expand Up @@ -314,6 +309,26 @@ def verify_connectivity(self, **config):
"""
raise NotImplementedError

@experimental("Feature support query, based on Bolt Protocol Version and Neo4j Server Version will change in the future.")
def supports_multi_db(self):
""" Check if the server or cluster supports multi-databases.

:return: Returns true if the server or cluster the driver connects to supports multi-databases, otherwise false.
:rtype: bool
"""
from neo4j.io._bolt4x0 import Bolt4x0

multi_database = False
cx = self._pool.acquire(access_mode=READ_ACCESS, timeout=self._pool.workspace_config.connection_acquisition_timeout, database=self._pool.workspace_config.database)

# TODO: This logic should be inside the Bolt subclasses, because it can change depending on Bolt Protocol Version.
if cx.PROTOCOL_VERSION >= Bolt4x0.PROTOCOL_VERSION and cx.server_info.version_info() >= Version(4, 0, 0):
multi_database = True

self._pool.release(cx)

return multi_database


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

@classmethod
def open(cls, target, *, auth=None, **config):
"""
:param target:
:param auth:
:param config: The values that can be specified are found in :class: `neo4j.PoolConfig` and :class: `neo4j.WorkspaceConfig`

:return:
:rtype: :class: `neo4j.BoltDriver`
"""
from neo4j.io import BoltPool
address = cls.parse_target(target)
pool_config, default_workspace_config = Config.consume_chain(config, PoolConfig, WorkspaceConfig)
pool = BoltPool.open(address, auth=auth, **pool_config)
pool = BoltPool.open(address, auth=auth, pool_config=pool_config, workspace_config=default_workspace_config)
return cls(pool, default_workspace_config)

def __init__(self, pool, default_workspace_config):
Expand All @@ -338,6 +361,12 @@ def __init__(self, pool, default_workspace_config):
self._default_workspace_config = default_workspace_config

def session(self, **config):
"""
:param config: The values that can be specified are found in :class: `neo4j.SessionConfig`

:return:
:rtype: :class: `neo4j.Session`
"""
from neo4j.work.simple import Session
session_config = SessionConfig(self._default_workspace_config, config)
SessionConfig.consume(config) # Consume the config
Expand Down Expand Up @@ -372,16 +401,15 @@ def open(cls, *targets, auth=None, routing_context=None, **config):
from neo4j.io import Neo4jPool
addresses = cls.parse_targets(*targets)
pool_config, default_workspace_config = Config.consume_chain(config, PoolConfig, WorkspaceConfig)
pool = Neo4jPool.open(*addresses, auth=auth, routing_context=routing_context, **pool_config)
pool = Neo4jPool.open(*addresses, auth=auth, routing_context=routing_context, pool_config=pool_config, workspace_config=default_workspace_config)
return cls(pool, default_workspace_config)

def __init__(self, pool, default_workspace_config):
Routing.__init__(self, pool.routing_table.initial_routers)
Routing.__init__(self, pool.get_default_database_initial_router_addresses())
Driver.__init__(self, pool)
self._default_workspace_config = default_workspace_config

def session(self, **config):
from neo4j.work.simple import Session
session_config = SessionConfig(self._default_workspace_config, config)
SessionConfig.consume(config) # Consume the config
return Session(self._pool, session_config)
Expand All @@ -392,9 +420,6 @@ def pipeline(self, **config):
PipelineConfig.consume(config) # Consume the config
return Pipeline(self._pool, pipeline_config)

def get_routing_table(self):
return self._pool.routing_table

def verify_connectivity(self, **config):
"""
:raise ServiceUnavailable: raised if the server does not support routing or if routing support is broken.
Expand All @@ -406,11 +431,11 @@ def _verify_routing_connectivity(self):
from neo4j.exceptions import ServiceUnavailable
from neo4j._exceptions import BoltHandshakeError

table = self.get_routing_table()
table = self._pool.get_routing_table_for_default_database()
routing_info = {}
for ix in list(table.routers):
try:
routing_info[ix] = self._pool.fetch_routing_info(table.routers[0])
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)
except BoltHandshakeError as error:
routing_info[ix] = None

Expand Down
2 changes: 1 addition & 1 deletion neo4j/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
TRUST_ALL_CERTIFICATES = "TRUST_ALL_CERTIFICATES"

SYSTEM_DATABASE = "system"
DEFAULT_DATABASE = None
DEFAULT_DATABASE = None # Must be a non string hashable value


class Auth:
Expand Down
20 changes: 18 additions & 2 deletions neo4j/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,14 +304,15 @@ class SessionConfig(WorkspaceConfig):
#: Bookmarks
bookmarks = ()

# Default AccessMode
#: Default AccessMode
default_access_mode = WRITE_ACCESS
# access_mode = DeprecatedAlias("default_access_mode")


class TransactionConfig(Config):
""" Transaction configuration.
""" Transaction configuration. This is internal for now.

neo4j.session.begin_transaction
neo4j.Query
neo4j.unit_of_work

Expand All @@ -322,3 +323,18 @@ class TransactionConfig(Config):

#: Timeout
timeout = None # seconds


class RoutingConfig(Config):
""" Neo4jDriver routing settings. This is internal for now.
"""

#: Routing Table Purge_Delay
routing_table_purge_delay = 30.0 # seconds
# The TTL + routing_table_purge_delay should be used to check if the database routing table should be removed.

#: Max Routing Failures
# max_routing_failures = 1

#: Retry Timeout Delay
# retry_timeout_delay = 5.0 # seconds
Loading