Skip to content

Commit

Permalink
DRIVERS-2789 Convert Max Staleness Spec to Markdown
Browse files Browse the repository at this point in the history
  • Loading branch information
blink1073 committed Apr 30, 2024
1 parent d26a78e commit bb5f59e
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 226 deletions.
6 changes: 3 additions & 3 deletions scripts/migrate_to_md.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@
while curr.parent.name != 'source':
target = f'{curr.parent.name}/{target}'
curr = curr.parent
suffix = f'\S*/{target}'
rel_pattern = re.compile(f'(\.\.{suffix})')
md_pattern = re.compile(f'(\(http{suffix})')
suffix = fr'\S*/{target}'
rel_pattern = re.compile(fr'(\.\.{suffix})')
md_pattern = re.compile(fr'(\(http{suffix})')
html_pattern = re.compile(f'(http{suffix})')
abs_pattern = re.compile(f'(/source{suffix})')
for p in Path("source").rglob("*"):
Expand Down
1 change: 1 addition & 0 deletions source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- [Initial DNS Seedlist Discovery](initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md)
- [Load Balancer Support](load-balancers/load-balancers.md)
- [Logging](logging/logging.md)
- [Max Staleness Tests](max-staleness/max-staleness-tests.md)
- [MongoDB Driver Performance Benchmarking](benchmarking/benchmarking.md)
- [Server Selection](server-selection/server-selection.md)
- [Server Selection Test Plan](server-selection/server-selection-tests.md)
Expand Down
169 changes: 79 additions & 90 deletions source/max-staleness/max-staleness-tests.md
Original file line number Diff line number Diff line change
@@ -1,153 +1,142 @@
===================
Max Staleness Tests
===================
# Max Staleness Tests

These prose tests supplement the machine-readable YAML tests.

.. contents::

Connection string
=================
## Connection string

Tests of drivers' connection string parsing and validation.

Basic
-----
### Basic

maxStalenessSeconds is set to 120 from this connection string::
maxStalenessSeconds is set to 120 from this connection string:

mongodb://host/?readPreference=secondary&maxStalenessSeconds=120
```
mongodb://host/?readPreference=secondary&maxStalenessSeconds=120
```

No maxStalenessSeconds with mode "primary"
------------------------------------------
### No maxStalenessSeconds with mode "primary"

These connection strings are invalid because the mode is "primary", either
by default or explicitly::
These connection strings are invalid because the mode is "primary", either by default or explicitly:

mongodb://host/?maxStalenessSeconds=120
mongodb://host/?readPreference=primary&maxStalenessSeconds=120
```
mongodb://host/?maxStalenessSeconds=120
mongodb://host/?readPreference=primary&maxStalenessSeconds=120
```

Specifying "no max staleness" with "-1"
---------------------------------------
### Specifying "no max staleness" with "-1"

A MongoClient with this connection string has no max staleness, the same as
if "maxStalenessSeconds" were omitted from the connection string::
A MongoClient with this connection string has no max staleness, the same as if "maxStalenessSeconds" were omitted from
the connection string:

mongodb://host/?readPreference=secondary&maxStalenessSeconds=-1
```
mongodb://host/?readPreference=secondary&maxStalenessSeconds=-1
```

This connection string is valid and does not raise an error:

mongodb://host/?readPreference=primary&maxStalenessSeconds=-1
> <mongodb://host/?readPreference=primary&maxStalenessSeconds=-1>
No validation
-------------
### No validation

A MongoClient can be initialized with this connection string;
the small maxStalenessSeconds value causes no error initially::
A MongoClient can be initialized with this connection string; the small maxStalenessSeconds value causes no error
initially:

mongodb://host/?readPreference=secondary&maxStalenessSeconds=1
```
mongodb://host/?readPreference=secondary&maxStalenessSeconds=1
```

heartbeatFrequencyMS is configurable
====================================
## heartbeatFrequencyMS is configurable

Server Discovery and Monitoring was updated to accommodate the Max Staleness Spec:
heartbeatFrequencyMS MUST now be configurable in all drivers, not just single-threaded drivers.
Server Discovery and Monitoring was updated to accommodate the Max Staleness Spec: heartbeatFrequencyMS MUST now be
configurable in all drivers, not just single-threaded drivers.

Test that a user can set heartbeatFrequencyMS in the connection string::
Test that a user can set heartbeatFrequencyMS in the connection string:

mongodb://host/?heartbeatFrequencyMS=500
```
mongodb://host/?heartbeatFrequencyMS=500
```

Test that a client initialized with this string
checks a standalone server roughly twice per second.
Test that a client initialized with this string checks a standalone server roughly twice per second.

Driver Tests
============
## Driver Tests

Parse lastWriteDate
-------------------
### Parse lastWriteDate

Configure a client with heartbeatFrequencyMS of 500 milliseconds.

Connect to a MongoDB replica set member with maxWireVersion at least 5.
(Only replica set members with maxWireVersion 5 have a lastWriteDate in
the legacy hello reply.)
Connect to a MongoDB replica set member with maxWireVersion at least 5. (Only replica set members with maxWireVersion 5
have a lastWriteDate in the legacy hello reply.)

Insert a document and wait one second.

Get the client's ServerDescription for the server.
It must have a non-zero lastWriteDate.
Wait another second. [1]_
Get the client's ServerDescription for the server. It must have a non-zero lastWriteDate. Wait another second.[^1]

Insert a document and wait one second.

Get the client's ServerDescription for the server.
The ServerDescription's lastWriteDate must be greater than before,
Get the client's ServerDescription for the server. The ServerDescription's lastWriteDate must be greater than before,
but less than 10 seconds greater.

(This test is as lenient as possible,
while still testing that the driver parses lastWriteDate
and converts it to an appropriate unit.)

.. [1] This ensures the next insert occurs at least one second after server
selection (another write may have occurred from the noop writer just before
server selection if mongod was configured with periodicNoopIntervalSecs=1).
(This test is as lenient as possible, while still testing that the driver parses lastWriteDate and converts it to an
appropriate unit.)

Absent lastWriteDate
--------------------
### Absent lastWriteDate

Connect to a MongoDB server with maxWireVersion less than 5.
Check that the driver's ServerDescription for this server has no lastWriteDate,
represented with null, zero, or however the driver represents a non-value.
Connect to a MongoDB server with maxWireVersion less than 5. Check that the driver's ServerDescription for this server
has no lastWriteDate, represented with null, zero, or however the driver represents a non-value.

Direct connection to mongos
---------------------------
### Direct connection to mongos

Initialize a MongoClient with this connection string::
Initialize a MongoClient with this connection string:

mongodb://mongos/?readPreference=secondary&maxStalenessSeconds=120
```
mongodb://mongos/?readPreference=secondary&maxStalenessSeconds=120
```

Where "mongos" is the hostname and port
of a mongos server running wire protocol version 5+.
Execute a "findOne" operation.
The MongoClient must include following read preference element with its
"find" command::
Where "mongos" is the hostname and port of a mongos server running wire protocol version 5+. Execute a "findOne"
operation. The MongoClient must include following read preference element with its "find" command:

$readPreference: {
mode: "secondary",
maxStalenessSeconds: 120
}
```
$readPreference: {
mode: "secondary",
maxStalenessSeconds: 120
}
```

The "maxStalenessSeconds" element must be a BSON int32 or int64 type.

Do the same test with this connection string::
Do the same test with this connection string:

mongodb://mongos/?readPreference=secondary
```
mongodb://mongos/?readPreference=secondary
```

The read preference element sent to mongos must omit "maxStalenessSeconds".

Mongos
======
## Mongos

These tests MUST be added to the server code repository,
validating mongos's maxStalenessSeconds implementation.
These tests MUST be added to the server code repository, validating mongos's maxStalenessSeconds implementation.

maxStalenessSeconds and mode "primary"
--------------------------------------
### maxStalenessSeconds and mode "primary"

mongos MUST reject a read with::
mongos MUST reject a read with:

$readPreference: {mode: "primary", maxStalenessSeconds: 120}
```
$readPreference: {mode: "primary", maxStalenessSeconds: 120}
```

Validation
----------
### Validation

mongos MUST reject a read with ``maxStalenessSeconds`` that is not an int32 or int64.
mongos MUST reject a read with `maxStalenessSeconds` that is not an int32 or int64.

maxStalenessSeconds too small
-----------------------------
### maxStalenessSeconds too small

The minimum value of maxStalenessSeconds is 90. mongos MUST reject a read with::
The minimum value of maxStalenessSeconds is 90. mongos MUST reject a read with:

$readPreference: {mode: "secondary", maxStalenessSeconds: 89}
```
$readPreference: {mode: "secondary", maxStalenessSeconds: 89}
```

The error code MUST be 160.

[^1]: This ensures the next insert occurs at least one second after server selection (another write may have occurred from
the noop writer just before server selection if mongod was configured with periodicNoopIntervalSecs=1).
4 changes: 4 additions & 0 deletions source/max-staleness/max-staleness-tests.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

.. note::
This specification has been converted to Markdown and renamed to
`max-staleness-tests.md <max-staleness-tests.md>`_.
101 changes: 40 additions & 61 deletions source/max-staleness/tests/README.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,51 @@
===================
Max Staleness Tests
===================
# Max Staleness Tests

This directory contains platform-independent tests that drivers can use
to prove their conformance to the Max Staleness Spec. The tests
are provided in both YAML and JSON formats, and drivers may test against
whichever format is more convenient for them.
This directory contains platform-independent tests that drivers can use to prove their conformance to the Max Staleness
Spec. The tests are provided in both YAML and JSON formats, and drivers may test against whichever format is more
convenient for them.

Test Format and Use
-------------------
## Test Format and Use

YAML files contain the following setup for each test:

- ``heartbeatFrequencyMS``: optional int

- ``topology_description``: the state of a mocked cluster

- ``type``: the TopologyType

- ``servers``: a list of ServerDescriptions, each with:

- ``address``: a "host:port"

- ``type``: a ServerType

- ``avg_rtt_ms``: average round trip time in milliseconds [1]_

- ``lastWrite``: subdocument

- ``lastWriteDate``: nonzero int64, milliseconds since some past time

- ``maxWireVersion``: an int

- ``lastUpdateTime``: milliseconds since the Unix epoch

- ``read_preference``: a read preference document

For each test, create a MongoClient.
Configure it with the heartbeatFrequencyMS specified by the test,
or accept the driver's default heartbeatFrequencyMS if the test omits this field.

(Single-threaded and multi-threaded clients now make heartbeatFrequencyMS configurable.
This is a change in Server Discovery and Monitoring to support maxStalenessSeconds.
Before, multi-threaded clients were allowed to make it configurable or not.)

For each test, create a new TopologyDescription object initialized with the
values from ``topology_description``. Initialize ServerDescriptions from the
provided data. Create a ReadPreference object initialized with the values
from ``read_preference``. Select servers that match the ReadPreference.
- `heartbeatFrequencyMS`: optional int
- `topology_description`: the state of a mocked cluster
- `type`: the TopologyType
- `servers`: a list of ServerDescriptions, each with:
- `address`: a "host:port"
- `type`: a ServerType
- `avg_rtt_ms`: average round trip time in milliseconds[^1]
- `lastWrite`: subdocument
- `lastWriteDate`: nonzero int64, milliseconds since some past time
- `maxWireVersion`: an int
- `lastUpdateTime`: milliseconds since the Unix epoch
- `read_preference`: a read preference document

For each test, create a MongoClient. Configure it with the heartbeatFrequencyMS specified by the test, or accept the
driver's default heartbeatFrequencyMS if the test omits this field.

(Single-threaded and multi-threaded clients now make heartbeatFrequencyMS configurable. This is a change in Server
Discovery and Monitoring to support maxStalenessSeconds. Before, multi-threaded clients were allowed to make it
configurable or not.)

For each test, create a new TopologyDescription object initialized with the values from `topology_description`.
Initialize ServerDescriptions from the provided data. Create a ReadPreference object initialized with the values from
`read_preference`. Select servers that match the ReadPreference.

Each test specifies that it expects an error, or specifies two sets of servers:

- ``error: true``
- ``suitable_servers``: the set of servers in the TopologyDescription
that are suitable for the ReadPreference, without taking ``avg_rtt_ms``
into account.
- ``in_latency_window``: the set of suitable servers whose round trip time
qualifies them according to the default latency threshold of 15ms.
In each test there is one server in the latency window, to ensure
tests pass or fail deterministically.
- `error: true`
- `suitable_servers`: the set of servers in the TopologyDescription that are suitable for the ReadPreference, without
taking `avg_rtt_ms` into account.
- `in_latency_window`: the set of suitable servers whose round trip time qualifies them according to the default latency
threshold of 15ms. In each test there is one server in the latency window, to ensure tests pass or fail
deterministically.

If the file contains ``error: true``, drivers MUST test that they throw an
error during server selection due to an invalid read preference. For other
files, drivers MUST test that they correctly select the set of servers in
``in_latency_window``.
If the file contains `error: true`, drivers MUST test that they throw an error during server selection due to an invalid
read preference. For other files, drivers MUST test that they correctly select the set of servers in
`in_latency_window`.

Drivers MAY also test that before filtration by latency, they select the
specified set of "suitable" servers.
Drivers MAY also test that before filtration by latency, they select the specified set of "suitable" servers.

.. [1] ``avg_rtt_ms`` is included merely for consistency with
Server Selection tests. It is not significant in Max Staleness tests.
[^1]: `avg_rtt_ms` is included merely for consistency with Server Selection tests. It is not significant in Max Staleness
tests.
Loading

0 comments on commit bb5f59e

Please sign in to comment.