Skip to content

Commit 90cfaef

Browse files
authored
DRIVERS-2530: Defer checking for session support until after connection checkout (#1379)
1 parent ef669cd commit 90cfaef

File tree

2 files changed

+70
-73
lines changed

2 files changed

+70
-73
lines changed

source/sessions/driver-sessions.rst

Lines changed: 28 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,9 @@ instances at the same time (see the Server Session Pool section). Additionally,
203203
a ``ClientSession`` may only ever be associated with one ``ServerSession`` for
204204
its lifetime.
205205

206-
Drivers MUST report an error if sessions are not supported by the deployment
207-
(see How to Check Whether a Deployment Supports Sessions). This error MUST either
208-
be reported by ``startSession``, or be reported the first time the session is used
209-
for an operation.
206+
Drivers MUST NOT check for session support in `startSession`. Instead, if sessions
207+
are not supported, the error MUST be reported the first time the session is used
208+
for an operation (See `How to Tell Whether a Connection Supports Sessions`_).
210209

211210
Explicit vs implicit sessions
212211
-----------------------------
@@ -433,14 +432,14 @@ Existing database methods that start an implicit session
433432
--------------------------------------------------------
434433

435434
When an existing ``MongoDatabase`` method that does not take a session is called,
436-
the driver MUST check whether the deployment supports sessions (See How to
437-
Check Whether a Deployment Supports Session). If sessions are supported, the
438-
driver MUST behave as if a new ``ClientSession`` was started just for this one
435+
the driver MUST behave as if a new ``ClientSession`` was started just for this one
439436
operation and ended immediately after this operation completes. The actual
440437
implementation will likely involve calling ``client.startSession``, but that is not
441438
required by this spec. Regardless, please consult the startSession section to
442439
replicate the required steps for creating a session.
443-
Drivers MUST NOT consume a server session id until after the connection is checked out.
440+
The driver MUST NOT use the session if the checked out connection does not support sessions
441+
(see `How to Tell Whether a Connection Supports Sessions`_) and, in all cases, MUST NOT consume a server
442+
session id until after the connection is checked out and session support is confirmed.
444443

445444
MongoCollection changes
446445
=======================
@@ -475,13 +474,14 @@ Existing collection methods that start an implicit session
475474
----------------------------------------------------------
476475

477476
When an existing ``MongoCollection`` method that does not take a session is called,
478-
the driver MUST check whether the deployment supports sessions (See How to
479-
Check Whether a Deployment Supports Session). If sessions are supported, the
480-
driver MUST behave as if a new ``ClientSession`` was started just for this one
477+
the driver MUST behave as if a new ``ClientSession`` was started just for this one
481478
operation and ended immediately after this operation completes. The actual
482479
implementation will likely involve calling ``client.startSession``, but that is not
483-
required by this spec.
484-
Drivers MUST create an implicit session only after successfully checking out a connection.
480+
required by this spec. Regardless, please consult the startSession section to
481+
replicate the required steps for creating a session.
482+
The driver MUST NOT use the session if the checked out connection does not support sessions
483+
(see `How to Tell Whether a Connection Supports Sessions`_) and, in all cases, MUST NOT consume a server
484+
session id until after the connection is checked out and session support is confirmed.
485485

486486
Sessions and Cursors
487487
====================
@@ -502,68 +502,32 @@ A driver SHOULD NOT attempt to release the acquired session before connection ch
502502

503503
Explicit sessions MAY be changed to allocate a server session similarly.
504504

505-
How to Check Whether a Deployment Supports Sessions
505+
How to Tell Whether a Connection Supports Sessions
506506
===================================================
507507

508-
A driver can determine whether a deployment supports sessions by checking whether
509-
the ``logicalSessionTimeoutMinutes`` property of the ``TopologyDescription`` has
510-
a value or not. If it has a value the deployment supports sessions. However, in
511-
order for this determination to be valid, the driver MUST be connected to at least
512-
one server of a type that is `data-bearing
513-
<https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#data-bearing-server-type>`_.
514-
Therefore, the detailed steps to determine whether sessions are supported are:
515-
516-
1. If the ``TopologyDescription`` and connection type indicate that
517-
518-
* the driver is not connected to any servers, OR
519-
* is not a direct connection AND is not connected to a data-bearing server
520-
521-
then a driver must do a server selection for any server whose type is data-bearing.
522-
Server selection will either time out or result in a ``TopologyDescription`` that
523-
includes at least one connected, data-bearing server.
508+
A driver can determine whether a connection supports sessions by checking whether
509+
the ``logicalSessionTimeoutMinutes`` property of the establishing handshake response has
510+
a value or not. If it has a value, sessions are supported.
524511

525-
2. Having verified in step 1 that the ``TopologyDescription`` includes at least
526-
one connected server a driver can now determine whether sessions are supported
527-
by inspecting the ``TopologyType`` and ``logicalSessionTimeoutMinutes`` property.
528-
When the ``TopologyType`` is ``LoadBalanced``, sessions are always supported.
512+
In the case of an explicit session, if sessions are not supported, the driver MUST raise an error.
513+
In the case of an implicit session, if sessions are not supported, the driver MUST ignore the session.
529514

530-
Possible race conditions when checking whether a deployment supports sessions
531-
-----------------------------------------------------------------------------
515+
Possible race condition when checking for session support
516+
---------------------------------------------------------
532517

533-
There are some possible race conditions that can happen between the time the
518+
There is a possible race condition that can happen between the time the
534519
driver checks whether sessions are supported and subsequently sends a command
535520
to the server:
536521

537-
* The TopologyDescription might be stale and no longer be accurate because it
538-
has been a few seconds since the last heartbeat.
539-
540-
* The TopologyDescription might be accurate at the time the driver checks
541-
whether sessions are supported, but by the time the driver sends a command to
542-
the server it might no longer be accurate.
543-
544-
* The TopologyDescription might be based on connections to a subset of the
545-
servers and it is possible that as the driver connects to more servers the
546-
driver might discover that sessions aren't supported after all.
547-
548522
* The server might have supported sessions at the time the connection was first
549523
opened (and reported a value for logicalSessionTimeoutMinutes in the initial
550524
response to the `handshake <https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst>`_),
551525
but have subsequently been downgraded to not support sessions. The server does
552-
not close the socket in this scenario, and the driver will forever conclude that
553-
the server at the other end of this connection supports sessions. This scenario
554-
will only be a problem until the next heartbeat against that server.
555-
556-
These race conditions are particularly insidious when the driver decides to
557-
start an implicit session based on the conclusion that sessions are supported.
558-
We don't want existing applications that don't use explicit sessions to fail
559-
when using implicit sessions.
560-
561-
To handle these race conditions, the driver MUST ignore any implicit session if
562-
at the point it is sending a command to a specific server it turns out that
563-
that particular server doesn't support sessions after all. This handles the
564-
first three race conditions. There is nothing that the driver can do about the
565-
final race condition, and the server will just return an error in this
566-
scenario.
526+
not close the socket in this scenario, so the driver will conclude that
527+
the server at the other end of this connection supports sessions.
528+
529+
There is nothing that the driver can do about this race condition, and the server
530+
will just return an error in this scenario.
567531

568532
Sending the session ID to the server on all commands
569533
====================================================
@@ -1187,3 +1151,4 @@ Changelog
11871151
:2022-03-24: ServerSession Pooling is required and clarifies session acquisition bounding
11881152
:2022-06-13: Move prose tests to test README and apply new ordering
11891153
:2022-10-05: Remove spec front matter
1154+
:2023-02-24: Defer checking for session support until after connection checkout

source/sessions/tests/README.rst

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,34 @@ The YAML and JSON files in this directory are platform-independent tests
1313
meant to exercise a driver's implementation of sessions. These tests utilize the
1414
`Unified Test Format <../../unified-test-format/unified-test-format.rst>`__.
1515

16-
Several prose tests, which are not easily expressed in YAML, are also presented
17-
in the Driver Sessions Spec. Those tests will need to be manually implemented
18-
by each driver.
19-
2016
Snapshot session tests
21-
======================
22-
Snapshot sessions tests require server of version 5.0 or higher and
23-
replica set or a sharded cluster deployment.
24-
Default snapshot history window on the server is 5 minutes. Running the test in debug mode, or in any other slow configuration
17+
~~~~~~~~~~~~~~~~~~~~~~
18+
The default snapshot history window on the server is 5 minutes. Running the test in debug mode, or in any other slow configuration
2519
may lead to `SnapshotTooOld` errors. Drivers can work around this issue by increasing the server's `minSnapshotHistoryWindowInSeconds` parameter, for example:
2620

2721
.. code:: python
2822
29-
client.admin.command('setParameter', 1, minSnapshotHistoryWindowInSeconds=60)
23+
client.admin.command('setParameter', 1, minSnapshotHistoryWindowInSeconds=600)
24+
25+
Testing against servers that do not support sessions
26+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27+
Since all regular 3.6+ servers support sessions, the prose tests which test for session non-support SHOULD
28+
use a mongocryptd server as the test server (available with server versions 4.2+); however, if future versions of mongocryptd
29+
support sessions or if mongocryptd is not a viable option for the driver implementing these tests, another server MAY be
30+
substituted as long as it does not return a non-null value for ``logicalSessionTimeoutMinutes``;
31+
in the event that no such server is readily available, a mock server may be used as a last resort.
32+
33+
As part of the test setup for these cases, create a ``MongoClient`` pointed at the test server with the options
34+
specified in the test case and verify that the test server does NOT define a value for ``logicalSessionTimeoutMinutes``
35+
by sending a hello command and checking the response.
3036

3137
Prose tests
32-
```````````
38+
===========
3339

3440
1. Setting both ``snapshot`` and ``causalConsistency`` to true is not allowed
3541
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
42+
Snapshot sessions tests require server of version 5.0 or higher and
43+
replica set or a sharded cluster deployment.
3644

3745
* ``client.startSession(snapshot = true, causalConsistency = true)``
3846
* Assert that an error was raised by driver
@@ -234,6 +242,29 @@ This test only applies to drivers that allow authentication to be changed on the
234242
* Call ``findOne`` using the session as an explicit session
235243
* Assert that the driver returned an error because the session is owned by a different user
236244

245+
18. Implicit session is ignored if connection does not support sessions
246+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
247+
248+
Refer to `Testing against servers that do not support sessions`_ and configure a ``MongoClient``
249+
with command monitoring enabled.
250+
251+
* Send a read command to the server (e.g., ``findOne``), ignoring any errors from the server response
252+
* Check the corresponding ``commandStarted`` event: verify that ``lsid`` is not set
253+
* Send a write command to the server (e.g., ``insertOne``), ignoring any errors from the server response
254+
* Check the corresponding ``commandStarted`` event: verify that lsid is not set
255+
256+
19. Explicit session raises an error if connection does not support sessions
257+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
258+
259+
Refer to `Testing against servers that do not support sessions`_ and configure a ``MongoClient``
260+
with default options.
261+
262+
* Create a new explicit session by calling ``startSession`` (this MUST NOT error)
263+
* Attempt to send a read command to the server (e.g., ``findOne``) with the explicit session passed in
264+
* Assert that a client-side error is generated indicating that sessions are not supported
265+
* Attempt to send a write command to the server (e.g., ``insertOne``) with the explicit session passed in
266+
* Assert that a client-side error is generated indicating that sessions are not supported
267+
237268
Changelog
238269
=========
239270

@@ -242,3 +273,4 @@ Changelog
242273
:2021-07-30: Use numbering for prose test
243274
:2022-02-11: Convert legacy tests to unified format
244275
:2022-06-13: Relocate prose test from spec document and apply new ordering
276+
:2023-02-24: Fix formatting and add new prose tests 18 and 19

0 commit comments

Comments
 (0)