Skip to content

Commit de87abc

Browse files
committed
Introduce aura_instance_id parameter
allow to explicitly pass it. This is important if the original Aura instance id not part of the uri. Such as for multi-db support ref GDSA-283
1 parent ebad547 commit de87abc

File tree

7 files changed

+55
-6
lines changed

7 files changed

+55
-6
lines changed

changelog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
## Improvements
1414

1515
- Added retries to verifying connection and authentication of DB connection provided to `GdsSessions.getOrCreate`
16-
16+
- `GdsSessions.get_or_create` now allows to specify the `aura_instance_id`. This is required if the instance id could not be derived from the provided database connection URI.
1717

1818
## Other changes
1919

doc/modules/ROOT/pages/graph-analytics-serverless.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ sessions.get_or_create(
8585
db_connection: Optional[DbmsConnectionInfo] = None,
8686
ttl: Optional[timedelta] = None,
8787
cloud_location: Optional[CloudLocation] = None,
88+
aura_instance_id: Optional[str] = None,
8889
timeout: Optional[int] = None,
8990
neo4j_driver_options: Optional[dict[str, Any]] = None,
9091
arrow_client_options: Optional[dict[str, Any]] = None,
@@ -100,6 +101,7 @@ sessions.get_or_create(
100101
| db_connection | https://neo4j.com/docs/graph-data-science-client/{docs-version}/api/sessions/DbmsConnectionInfo[DbmsConnectionInfo] | yes | None | Bolt server URL, username, and password to a Neo4j DBMS. Required for the Attached and Self-managed types. Alternatively to username and password, you can provide a `neo4j.Auth` https://neo4j.com/docs/python-manual/current/connect-advanced/#authentication-methods[object].
101102
| ttl | datetime.timedelta | yes | 1h | Time-to-live for the session.
102103
| cloud_location | https://neo4j.com/docs/graph-data-science-client/{docs-version}/api/sessions/cloud_location[CloudLocation] | yes | None | Aura-supported cloud provider and region where the GDS Session will run. Required for the Self-managed and Standalone types.
104+
| aura_instance_id | str | yes | None | Aura instance ID for the session. Required for the Attached type, if the id could not be derived from the DB connection.
103105
| timeout | int | yes | None | Seconds to wait for the session to enter Ready state. If the time is exceeded, an error will be returned.
104106
| neo4j_driver_options | dict[str, any] | yes | None | Additional options passed to the Neo4j driver to the Neo4j DBMS. Only relevant if `db_connection` is specified.
105107
| arrow_client_options | dict[str, any] | yes | None | Additional options passed to the Arrow Flight Client used to connect to the Session.

graphdatascience/session/dbms_connection_info.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import os
44
from dataclasses import dataclass
5+
from urllib.parse import urlparse
56

67
from neo4j import Auth, basic_auth
78

@@ -38,6 +39,14 @@ def get_auth(self) -> Auth | None:
3839
auth = basic_auth(self.username, self.password)
3940
return auth
4041

42+
def hosted_in_aura(self) -> bool:
43+
"""
44+
Returns:
45+
True if the DBMS is hosted in Aura, False otherwise.
46+
"""
47+
host = urlparse(self.uri).hostname
48+
return host is not None and host.endswith("databases.neo4j.io")
49+
4150
@staticmethod
4251
def from_env() -> DbmsConnectionInfo:
4352
"""

graphdatascience/session/dedicated_sessions.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def get_or_create(
6161
db_connection: DbmsConnectionInfo | None = None,
6262
ttl: timedelta | None = None,
6363
cloud_location: CloudLocation | None = None,
64+
aura_instance_id: str | None = None,
6465
timeout: int | None = None,
6566
neo4j_driver_options: dict[str, Any] | None = None,
6667
arrow_client_options: dict[str, Any] | None = None,
@@ -74,12 +75,17 @@ def get_or_create(
7475
else:
7576
db_runner = self._create_db_runner(db_connection, neo4j_driver_options)
7677

77-
dbid = AuraApi.extract_id(db_connection.uri)
78-
aura_db_instance = self._aura_api.list_instance(dbid)
78+
aura_instance_id = AuraApi.extract_id(db_connection.uri) if not aura_instance_id else aura_instance_id
79+
aura_db_instance = self._aura_api.list_instance(aura_instance_id)
7980

8081
if aura_db_instance is None:
8182
if not cloud_location:
82-
raise ValueError("cloud_location must be provided for sessions against a self-managed DB.")
83+
if db_connection.hosted_in_aura():
84+
raise ValueError(
85+
f"Could not derive Aura instance id from the URI `{db_connection.uri}`. Please provide the instance id via the `aura_instance_id` argument, or specify a cloud location if the DBMS is self-managed."
86+
)
87+
else:
88+
raise ValueError("cloud_location must be provided for sessions against a self-managed DB.")
8389

8490
session_details = self._get_or_create_self_managed_session(
8591
session_name, memory.value, cloud_location, ttl
@@ -88,7 +94,9 @@ def get_or_create(
8894
if cloud_location is not None:
8995
raise ValueError("cloud_location cannot be provided for sessions against an AuraDB.")
9096

91-
session_details = self._get_or_create_attached_session(session_name, memory.value, dbid, ttl)
97+
session_details = self._get_or_create_attached_session(
98+
session_name, memory.value, aura_instance_id, ttl
99+
)
92100

93101
self._await_session_running(session_details, timeout)
94102

graphdatascience/session/gds_sessions.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ def get_or_create(
107107
timeout: int | None = None,
108108
neo4j_driver_config: dict[str, Any] | None = None,
109109
arrow_client_options: dict[str, Any] | None = None,
110+
aura_instance_id: str | None = None,
110111
) -> AuraGraphDataScience:
111112
"""
112113
Retrieves an existing session with the given session name and database connection,
@@ -122,8 +123,9 @@ def get_or_create(
122123
ttl: (timedelta | None): The sessions time to live after inactivity in seconds.
123124
cloud_location (CloudLocation | None): The cloud location. Required if the GDS session is for a self-managed database.
124125
timeout (int | None): Optional timeout (in seconds) when waiting for session to become ready. If unset the method will wait forever. If set and session does not become ready an exception will be raised. It is user responsibility to ensure resource gets cleaned up in this situation.
125-
neo4j_driver_config (dict[str, Any] | None): Optional configuration for the Neo4j driver to the Neo4j DBMS. Only relevant if `db_connection` is specified..
126+
neo4j_driver_config (dict[str, Any] | None): Optional configuration for the Neo4j driver to the Neo4j DBMS. Only relevant if `db_connection` is specified..
126127
arrow_client_options (dict[str, Any] | None): Optional configuration for the Arrow Flight client.
128+
aura_instance_id (str | None): The Aura instance id. Required if the database is in Aura but its instance id cannot be inferred from the connection information.
127129
Returns:
128130
AuraGraphDataScience: The session.
129131
"""
@@ -132,6 +134,7 @@ def get_or_create(
132134
memory,
133135
db_connection=db_connection,
134136
ttl=ttl,
137+
aura_instance_id=aura_instance_id,
135138
cloud_location=cloud_location,
136139
timeout=timeout,
137140
neo4j_driver_options=neo4j_driver_config,

graphdatascience/tests/unit/session/test_dbms_connection_info.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,10 @@ def test_dbms_connection_info_fail_on_auth_and_username() -> None:
3939
)
4040
else:
4141
assert False, "Expected ValueError was not raised"
42+
43+
44+
def test_dbms_connection_info_hosted_in_aura() -> None:
45+
assert DbmsConnectionInfo(uri="bolt://something.databases.neo4j.io").hosted_in_aura()
46+
assert DbmsConnectionInfo(uri="bolt://something.databases.neo4j.io:7474").hosted_in_aura()
47+
48+
assert not DbmsConnectionInfo(uri="bolt://something.neo4j.com").hosted_in_aura()

graphdatascience/tests/unit/test_dedicated_sessions.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,26 @@ def test_get_or_create_for_without_cloud_location(mocker: MockerFixture, aura_ap
614614
)
615615

616616

617+
def test_get_or_create_for_non_derivable_aura_instance_id(mocker: MockerFixture, aura_api: AuraApi) -> None:
618+
sessions = DedicatedSessions(aura_api)
619+
patch_neo4j_query_runner(mocker)
620+
621+
with pytest.raises(
622+
ValueError,
623+
match=re.escape(
624+
"Could not derive Aura instance id from the URI `neo4j+s://06cba79f.databases.neo4j.io`. Please provide the instance id via the `aura_instance_id` argument, or specify a cloud location if the DBMS is self-managed."
625+
),
626+
):
627+
sessions.get_or_create(
628+
"my-session",
629+
SessionMemory.m_8GB,
630+
DbmsConnectionInfo(
631+
"neo4j+s://06cba79f.databases.neo4j.io", "dbuser", "db_pw"
632+
), # not part of list instances result
633+
cloud_location=None,
634+
)
635+
636+
617637
def test_get_or_create_failed_session(mocker: MockerFixture, aura_api: AuraApi) -> None:
618638
db = _setup_db_instance(aura_api)
619639

0 commit comments

Comments
 (0)