Skip to content

Commit d6f35fa

Browse files
Merge branch '5.0' into feature/remove-null-tests-for-ids
2 parents 8b5ecdb + 1becfc5 commit d6f35fa

36 files changed

+1075
-436
lines changed

CHANGELOG.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,9 @@
7676
It now raises a `ResultConsumedError`.
7777
- New method `Result.closed()` can be used to check for this condition if
7878
necessary.
79-
- `driver.verify_connectivity()`
80-
- All keyword arguments have been deprecated (they were experimental).
81-
They are now ignored and will be removed in a future release.
82-
- The undocumented return value has been removed. If you need information
83-
about the remote server, use `driver.get_server_info()` instead.
79+
- The undocumented return value of `driver.verify_connectivity()` has been
80+
removed. If you need information about the remote server, use
81+
`driver.get_server_info()` instead.
8482
- Transaction functions (a.k.a. managed transactions):
8583
The first argument of transaction functions is now a `ManagedTransaction`
8684
object. It behaves exactly like a regular `Transaction` object, except it

docs/source/api.rst

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ Driver Configuration
160160

161161
Additional configuration can be provided via the :class:`neo4j.Driver` constructor.
162162

163-
163+
+ :ref:`session-connection-timeout-ref`
164+
+ :ref:`update-routing-table-timeout-ref`
164165
+ :ref:`connection-acquisition-timeout-ref`
165166
+ :ref:`connection-timeout-ref`
166167
+ :ref:`encrypted-ref`
@@ -175,12 +176,63 @@ Additional configuration can be provided via the :class:`neo4j.Driver` construct
175176
+ :ref:`user-agent-ref`
176177

177178

179+
.. _session-connection-timeout-ref:
180+
181+
``session_connection_timeout``
182+
------------------------------
183+
The maximum amount of time in seconds the session will wait when trying to
184+
establish a usable read/write connection to the remote host.
185+
This encompasses *everything* that needs to happen for this, including,
186+
if necessary, updating the routing table, fetching a connection from the pool,
187+
and, if necessary fully establishing a new connection with the reader/writer.
188+
189+
Since this process may involve updating the routing table, acquiring a
190+
connection from the pool, or establishing a new connection, it should be chosen
191+
larger than :ref:`update-routing-table-timeout-ref`,
192+
:ref:`connection-acquisition-timeout-ref`, and :ref:`connection-timeout-ref`.
193+
194+
:Type: ``float``
195+
:Default: ``120.0``
196+
197+
.. versionadded:: 4.4.5
198+
199+
.. versionchanged:: 5.0
200+
201+
The default value was changed from ``float("inf")`` to ``120.0``.
202+
203+
204+
.. _update-routing-table-timeout-ref:
205+
206+
``update_routing_table_timeout``
207+
--------------------------------
208+
The maximum amount of time in seconds the driver will attempt to fetch a new
209+
routing table. This encompasses *everything* that needs to happen for this,
210+
including fetching connections from the pool, performing handshakes, and
211+
requesting and receiving a fresh routing table.
212+
213+
Since this process may involve acquiring a connection from the pool, or
214+
establishing a new connection, it should be chosen larger than
215+
:ref:`connection-acquisition-timeout-ref` and :ref:`connection-timeout-ref`.
216+
217+
This setting only has an effect for :ref:`neo4j-driver-ref`, but not for
218+
:ref:`bolt-driver-ref` as it does no routing at all.
219+
220+
:Type: ``float``
221+
:Default: ``90.0``
222+
223+
.. versionadded:: 4.4.5
224+
225+
178226
.. _connection-acquisition-timeout-ref:
179227

180228
``connection_acquisition_timeout``
181229
----------------------------------
182-
The maximum amount of time in seconds a session will wait when requesting a connection from the connection pool.
183-
Since the process of acquiring a connection may involve creating a new connection, ensure that the value of this configuration is higher than the configured :ref:`connection-timeout-ref`.
230+
The maximum amount of time in seconds the driver will wait to either acquire an
231+
idle connection from the pool (including potential liveness checks) or create a
232+
new connection when the pool is not full and all existing connection are in use.
233+
234+
Since this process may involve opening a new connection including handshakes,
235+
it should be chosen larger than :ref:`connection-timeout-ref`.
184236

185237
:Type: ``float``
186238
:Default: ``60.0``
@@ -190,7 +242,11 @@ Since the process of acquiring a connection may involve creating a new connectio
190242

191243
``connection_timeout``
192244
----------------------
193-
The maximum amount of time in seconds to wait for a TCP connection to be established.
245+
The maximum amount of time in seconds to wait for a TCP connection to be
246+
established.
247+
248+
This *does not* include any handshake(s), or authentication required before the
249+
connection can be used to perform database related work.
194250

195251
:Type: ``float``
196252
:Default: ``30.0``
@@ -224,7 +280,6 @@ Specify whether TCP keep-alive should be enabled.
224280

225281
``max_connection_lifetime``
226282
---------------------------
227-
228283
The maximum duration in seconds that the driver will keep a connection for before being removed from the pool.
229284

230285
:Type: ``float``
@@ -611,16 +666,21 @@ The default access mode.
611666

612667
A session can be given a default access mode on construction.
613668

614-
This applies only in clustered environments and determines whether transactions carried out within that session should be routed to a ``read`` or ``write`` server by default.
669+
This applies only in clustered environments and determines whether transactions
670+
carried out within that session should be routed to a ``read`` or ``write``
671+
server by default.
615672

616-
Transactions (see :ref:`managed-transactions-ref`) within a session can override the access mode passed to that session on construction.
673+
Transactions (see :ref:`managed-transactions-ref`) within a session override the
674+
access mode passed to that session on construction.
617675

618676
.. note::
619-
The driver does not parse Cypher queries and cannot determine whether the access mode should be ``neo4j.ACCESS_WRITE`` or ``neo4j.ACCESS_READ``.
620-
Since the access mode is not passed to the server, this can allow a ``neo4j.ACCESS_WRITE`` statement to be executed for a ``neo4j.ACCESS_READ`` call on a single instance.
621-
Clustered environments are not susceptible to this loophole as cluster roles prevent it.
622-
This behaviour should not be relied upon as the loophole may be closed in a future release.
623-
677+
The driver does not parse Cypher queries and cannot determine whether the
678+
access mode should be ``neo4j.ACCESS_WRITE`` or ``neo4j.ACCESS_READ``.
679+
This setting is only meant to enable the driver to perform correct routing,
680+
*not* for enforcing access control. This means that, depending on the server
681+
version and settings, the server or cluster might allow a write-statement to
682+
be executed even when ``neo4j.ACCESS_READ`` is chosen. This behaviour should
683+
not be relied upon as it can change with the server.
624684

625685
:Type: ``neo4j.WRITE_ACCESS``, ``neo4j.READ_ACCESS``
626686
:Default: ``neo4j.WRITE_ACCESS``

docs/source/index.rst

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ To deactivate the current active virtual environment, use:
9191
Quick Example
9292
*************
9393

94-
Creating nodes.
94+
Creating nodes and relationships.
9595

9696
.. code-block:: python
9797
@@ -100,15 +100,17 @@ Creating nodes.
100100
uri = "neo4j://localhost:7687"
101101
driver = GraphDatabase.driver(uri, auth=("neo4j", "password"))
102102
103+
def create_person(tx, name):
104+
tx.run("CREATE (a:Person {name: $name})", name=name)
105+
103106
def create_friend_of(tx, name, friend):
104107
tx.run("MATCH (a:Person) WHERE a.name = $name "
105108
"CREATE (a)-[:KNOWS]->(:Person {name: $friend})",
106109
name=name, friend=friend)
107110
108111
with driver.session() as session:
112+
session.write_transaction(create_person, "Alice")
109113
session.write_transaction(create_friend_of, "Alice", "Bob")
110-
111-
with driver.session() as session:
112114
session.write_transaction(create_friend_of, "Alice", "Carl")
113115
114116
driver.close()
@@ -126,8 +128,8 @@ Finding nodes.
126128
def get_friends_of(tx, name):
127129
friends = []
128130
result = tx.run("MATCH (a:Person)-[:KNOWS]->(f) "
129-
"WHERE a.name = $name "
130-
"RETURN f.name AS friend", name=name)
131+
"WHERE a.name = $name "
132+
"RETURN f.name AS friend", name=name)
131133
for record in result:
132134
friends.append(record["friend"])
133135
return friends

neo4j/_async/driver.py

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
# limitations under the License.
1717

1818

19+
import warnings
20+
1921
from .._async_compat.util import AsyncUtil
2022
from .._conf import (
2123
TrustAll,
@@ -36,6 +38,8 @@
3638
from ..meta import (
3739
deprecation_warn,
3840
experimental,
41+
experimental_warn,
42+
ExperimentalWarning,
3943
unclosed_resource_warn,
4044
)
4145

@@ -310,22 +314,34 @@ async def verify_connectivity(self, **config):
310314
Even if this method raises an exception, the driver still needs to
311315
be closed via :meth:`close` to free up all resources.
312316
317+
:param config: accepts the same configuration key-word arguments as
318+
:meth:`session`.
319+
320+
.. warning::
321+
All configuration key-word arguments are experimental.
322+
They might be changed or removed in any future version without
323+
prior notice.
324+
313325
:raises DriverError: if the driver cannot connect to the remote.
314326
Use the exception to further understand the cause of the
315327
connectivity problem.
316328
317-
.. versionchanged:: 5.0 the config parameters will be removed in
318-
version 6 0. It has no effect starting with version 5.0.
329+
.. versionchanged:: 5.0
330+
The undocumented return value has been removed.
331+
If you need information about the remote server, use
332+
:meth:`get_server_info` instead.
319333
"""
320334
if config:
321-
deprecation_warn(
322-
"verify_connectivity() will not accept any configuration "
323-
"parameters starting with version 6.0."
335+
experimental_warn(
336+
"All configuration key-word arguments to "
337+
"verify_connectivity() are experimental. They might be "
338+
"changed or removed in any future version without prior "
339+
"notice."
324340
)
341+
async with self.session(**config) as session:
342+
await session._get_server_info()
325343

326-
await self.get_server_info()
327-
328-
async def get_server_info(self):
344+
async def get_server_info(self, **config):
329345
"""Get information about the connected Neo4j server.
330346
331347
Try to establish a working read connection to the remote server or a
@@ -339,6 +355,14 @@ async def get_server_info(self):
339355
Even if this method raises an exception, the driver still needs to
340356
be closed via :meth:`close` to free up all resources.
341357
358+
:param config: accepts the same configuration key-word arguments as
359+
:meth:`session`.
360+
361+
.. warning::
362+
All configuration key-word arguments are experimental.
363+
They might be changed or removed in any future version without
364+
prior notice.
365+
342366
:rtype: ServerInfo
343367
344368
:raises DriverError: if the driver cannot connect to the remote.
@@ -347,7 +371,14 @@ async def get_server_info(self):
347371
348372
.. versionadded:: 5.0
349373
"""
350-
async with self.session() as session:
374+
if config:
375+
experimental_warn(
376+
"All configuration key-word arguments to "
377+
"verify_connectivity() are experimental. They might be "
378+
"changed or removed in any future version without prior "
379+
"notice."
380+
)
381+
async with self.session(**config) as session:
351382
return await session._get_server_info()
352383

353384
@experimental("Feature support query, based on Bolt protocol version and Neo4j server version will change in the future.")

neo4j/_async/io/_bolt.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ async def ping(cls, address, *, timeout=None, **config):
264264
except (ServiceUnavailable, SessionExpired, BoltHandshakeError):
265265
return None
266266
else:
267-
AsyncBoltSocket.close_socket(s)
267+
await AsyncBoltSocket.close_socket(s)
268268
return protocol_version
269269

270270
@classmethod
@@ -357,11 +357,6 @@ def time_remaining():
357357
connection.socket.set_deadline(time_remaining())
358358
try:
359359
await connection.hello()
360-
except SocketDeadlineExceeded as e:
361-
# connection._defunct = True
362-
raise ServiceUnavailable(
363-
"Timeout during initial handshake occurred"
364-
) from e
365360
finally:
366361
connection.socket.set_deadline(None)
367362
except Exception:
@@ -484,7 +479,7 @@ async def reset(self):
484479

485480
@abc.abstractmethod
486481
def goodbye(self):
487-
"""Append a GOODBYE message to the outgoing queued."""
482+
"""Append a GOODBYE message to the outgoing queue."""
488483
pass
489484

490485
def _append(self, signature, fields=(), response=None):
@@ -594,7 +589,7 @@ async def _set_defunct(self, message, error=None, silent=False):
594589
direct_driver = isinstance(self.pool, AsyncBoltPool)
595590

596591
if error:
597-
log.debug("[#%04X] %s", self.socket.getsockname()[1], error)
592+
log.debug("[#%04X] %r", self.socket.getsockname()[1], error)
598593
log.error(message)
599594
# We were attempting to receive data but the connection
600595
# has unexpectedly terminated. So, we need to close the

neo4j/_async/io/_common.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from struct import pack as struct_pack
2424

2525
from ..._async_compat.util import AsyncUtil
26+
from ..._exceptions import SocketDeadlineExceeded
2627
from ...exceptions import (
2728
Neo4jError,
2829
ServiceUnavailable,
@@ -70,7 +71,7 @@ async def _yield_messages(self, sock):
7071
# Reset for new message
7172
unpacker.reset()
7273

73-
except (OSError, socket.timeout) as error:
74+
except (OSError, socket.timeout, SocketDeadlineExceeded) as error:
7475
await AsyncUtil.callback(self.on_error, error)
7576

7677
async def pop(self):

0 commit comments

Comments
 (0)