Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fc43f30

Browse files
Unify connection_acquisition_timeout behavior (#1215)
The config option `connection_acquisition_timeout` now spans anything that's required to acquire a working connection from the pool. This includes * Potentially fetching a routing table This entails acquiring a connection in itself. * Bolt, TLS, TCP handshaking * Authentication * Any other required IO (e.g., DNS lookups) * Waiting for room in the pool * possibly more Previously, the timeout wold be restarted for auxiliary connection acquisitions like those for fetching a routing table.
1 parent adcd4f7 commit fc43f30

File tree

16 files changed

+462
-32
lines changed

16 files changed

+462
-32
lines changed

‎CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,15 @@ See also https://github.com/neo4j/neo4j-python-driver/wiki for a full changelog.
3939
(instead of internal `neo4j._exceptions.BoltHandshakeError`).
4040
`UnsupportedServerProduct` is now a subclass of `ServiceUnavailable` (instead of `Exception` directly).
4141
- `connection_acquisition_timeout` configuration option
42-
- `ValueError` on invalid values (instead of `ClientError`)
42+
- Raise `ValueError` on invalid values (instead of `ClientError`).
4343
- Consistently restrict the value to be strictly positive
4444
- New `ConnectionAcquisitionTimeoutError` (subclass of `DriverError`) instead of `ClientError`
4545
(subclass of `Neo4jError`) the timeout is exceeded.
4646
- This improves the differentiation between `DriverError` for client-side errors and `Neo4jError` for server-side
4747
errors.
48+
- The option now spans *anything* required to acquire a connection.
49+
This includes potential fetching of routing tables which in itself requires acquiring a connection.
50+
Previously, the timeout would be restarted for such auxiliary connection acquisitions.
4851
- `TypeError` instead of `ValueError` when passing a `Query` object to `Transaction.run`.
4952
- `TransactionError` (subclass of `DriverError`) instead of `ClientError` (subclass of `Neo4jError`) when calling
5053
`session.run()` while an explicit transaction is active on that session.

‎docs/source/api.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,11 @@ it should be chosen larger than :ref:`connection-timeout-ref`.
430430
:Type: ``float``
431431
:Default: ``60.0``
432432

433+
.. versionadded:: 6.0
434+
The setting now entails *anything* required to acquire a connection.
435+
This includes potential fetching of routing tables which in itself requires acquiring a connection.
436+
Previously, the timeout would be restarted for such auxiliary connection acquisitions.
437+
433438

434439
.. _connection-timeout-ref:
435440

‎src/neo4j/_async/io/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"AsyncBoltPool",
2929
"AsyncNeo4jPool",
3030
"ConnectionErrorHandler",
31+
"acquisition_timeout_to_deadline",
3132
]
3233

3334

@@ -40,6 +41,7 @@
4041
from ._bolt import AsyncBolt
4142
from ._common import ConnectionErrorHandler
4243
from ._pool import (
44+
acquisition_timeout_to_deadline,
4345
AcquisitionAuth,
4446
AcquisitionDatabase,
4547
AsyncBoltPool,

‎src/neo4j/_async/io/_pool.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ async def connection_creator():
260260
with self.lock:
261261
self.connections_reservations[address] -= 1
262262

263+
if deadline.expired():
264+
return None
263265
max_pool_size = self.pool_config.max_connection_pool_size
264266
infinite_pool_size = max_pool_size < 0 or max_pool_size == float("inf")
265267
with self.lock:
@@ -659,22 +661,21 @@ async def acquire(
659661
timeout,
660662
database,
661663
bookmarks,
662-
auth: AcquisitionAuth,
664+
auth: AcquisitionAuth|None,
663665
liveness_check_timeout,
664666
unprepared=False,
665667
database_callback=None,
666668
):
667669
# The access_mode and database is not needed for a direct connection,
668670
# it's just there for consistency.
669671
access_mode = check_access_mode(access_mode)
670-
_check_acquisition_timeout(timeout)
672+
deadline=acquisition_timeout_to_deadline(timeout)
671673
log.debug(
672674
"[#0000] _: <POOL> acquire direct connection, "
673675
"access_mode=%r, database=%r",
674676
access_mode,
675677
database,
676678
)
677-
deadline = Deadline.from_timeout_or_deadline(timeout)
678679
return await self._acquire(
679680
self.address, auth, deadline, liveness_check_timeout, unprepared
680681
)
@@ -969,7 +970,9 @@ async def update_routing_table(
969970
970971
:raise neo4j.exceptions.ServiceUnavailable:
971972
"""
972-
_check_acquisition_timeout(acquisition_timeout)
973+
acquisition_timeout = acquisition_timeout_to_deadline(
974+
acquisition_timeout
975+
)
973976
async with self.refresh_lock:
974977
routing_table = await self.get_routing_table(database)
975978
if routing_table is not None:
@@ -1147,7 +1150,7 @@ async def acquire(
11471150
database_callback=None,
11481151
):
11491152
access_mode = check_access_mode(access_mode)
1150-
_check_acquisition_timeout(timeout)
1153+
timeout=acquisition_timeout_to_deadline(timeout)
11511154

11521155
target_database = database.name
11531156

@@ -1242,6 +1245,13 @@ async def on_write_failure(self, address, database):
12421245
log.debug("[#0000] _: <POOL> table=%r", self.routing_tables)
12431246

12441247

1248+
def acquisition_timeout_to_deadline(timeout: object) -> Deadline:
1249+
if isinstance(timeout, Deadline):
1250+
return timeout
1251+
_check_acquisition_timeout(timeout)
1252+
return Deadline(timeout)
1253+
1254+
12451255
def _check_acquisition_timeout(timeout: object) -> None:
12461256
if not isinstance(timeout, (int, float)):
12471257
raise TypeError(

‎src/neo4j/_async/work/workspace.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
)
3131
from .._debug import AsyncNonConcurrentMethodChecker
3232
from ..io import (
33+
acquisition_timeout_to_deadline,
3334
AcquisitionAuth,
3435
AcquisitionDatabase,
3536
)
3637

3738

3839
if t.TYPE_CHECKING:
40+
from ..._deadline import Deadline
3941
from ...api import _TAuth
4042
from ...auth_management import (
4143
AsyncAuthManager,
@@ -159,13 +161,19 @@ async def _connect(self, access_mode, auth=None, **acquire_kwargs) -> None:
159161
await self._connection.fetch_all()
160162
await self._disconnect()
161163

164+
acquisition_deadline = acquisition_timeout_to_deadline(
165+
acquisition_timeout
166+
)
167+
162168
ssr_enabled = self._pool.ssr_enabled
163169
target_db = await self._get_routing_target_database(
164-
acquire_auth, ssr_enabled=ssr_enabled
170+
acquire_auth,
171+
ssr_enabled=ssr_enabled,
172+
acquisition_deadline=acquisition_deadline,
165173
)
166174
acquire_kwargs_ = {
167175
"access_mode": access_mode,
168-
"timeout": acquisition_timeout,
176+
"timeout": acquisition_deadline,
169177
"database": target_db,
170178
"bookmarks": await self._get_bookmarks(),
171179
"auth": acquire_auth,
@@ -188,7 +196,9 @@ async def _connect(self, access_mode, auth=None, **acquire_kwargs) -> None:
188196
)
189197
await self._disconnect()
190198
target_db = await self._get_routing_target_database(
191-
acquire_auth, ssr_enabled=False
199+
acquire_auth,
200+
ssr_enabled=False,
201+
acquisition_deadline=acquisition_deadline,
192202
)
193203
acquire_kwargs_["database"] = target_db
194204
self._connection = await self._pool.acquire(**acquire_kwargs_)
@@ -198,6 +208,7 @@ async def _get_routing_target_database(
198208
self,
199209
acquire_auth: AcquisitionAuth,
200210
ssr_enabled: bool,
211+
acquisition_deadline: Deadline,
201212
) -> AcquisitionDatabase:
202213
if (
203214
self._pinned_database
@@ -232,14 +243,13 @@ async def _get_routing_target_database(
232243
)
233244
return AcquisitionDatabase(cached_db, guessed=True)
234245

235-
acquisition_timeout = self._config.connection_acquisition_timeout
236246
log.debug("[#0000] _: <WORKSPACE> resolve home database")
237247
await self._pool.update_routing_table(
238248
database=self._config.database,
239249
imp_user=self._config.impersonated_user,
240250
bookmarks=await self._get_bookmarks(),
241251
auth=acquire_auth,
242-
acquisition_timeout=acquisition_timeout,
252+
acquisition_timeout=acquisition_deadline,
243253
database_callback=self._make_db_resolution_callback(),
244254
)
245255
return AcquisitionDatabase(self._config.database)

‎src/neo4j/_sync/io/__init__.py

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/neo4j/_sync/io/_pool.py

Lines changed: 15 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/neo4j/_sync/work/workspace.py

Lines changed: 15 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎testkitbackend/test_config.json

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@
1515
"'neo4j.datatypes.test_temporal_types.TestDataTypes.test_date_time_cypher_created_tz_id'":
1616
"test_subtest_skips.tz_id",
1717
"stub\\.routing\\.test_routing_v[0-9x]+\\.RoutingV[0-9x]+\\.test_should_drop_connections_failing_liveness_check":
18-
"Liveness check error handling is not (yet) unified: https://github.com/neo-technology/drivers-adr/pull/83",
19-
"'stub.homedb.test_homedb.TestHomeDbMixedCluster.test_connection_acquisition_timeout_during_fallback'":
20-
"TODO: 6.0 - pending unification: connection acquisition timeout should count towards the total time spent waiting for a connection (including routing, home db resolution, ...)",
21-
"'stub.driver_parameters.test_connection_acquisition_timeout_ms.TestConnectionAcquisitionTimeoutMs.test_does_encompass_router_route_response'":
22-
"TODO: 6.0 - pending unification: connection acquisition timeout should count towards the total time spent waiting for a connection (including routing, home db resolution, ...)",
23-
"'stub.driver_parameters.test_connection_acquisition_timeout_ms.TestConnectionAcquisitionTimeoutMs.test_router_handshake_shares_acquisition_timeout'":
24-
"TODO: 6.0 - pending unification: connection acquisition timeout should count towards the total time spent waiting for a connection (including routing, home db resolution, ...)"
18+
"Liveness check error handling is not (yet) unified: https://github.com/neo-technology/drivers-adr/pull/83"
2519
},
2620
"features": {
2721
"Feature:API:BookmarkManager": true,

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /