From 694ae4d0aa2c27eba8a6e071855806e63a01c9af Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Mon, 8 Dec 2025 14:20:27 -0500 Subject: [PATCH 01/12] DRIVERS-3344 - Add support for server selection's deprioritized servers to all topologies --- source/logging/logging.md | 2 +- source/retryable-reads/retryable-reads.md | 6 +- source/retryable-writes/retryable-writes.md | 10 +-- source/server-selection/server-selection.md | 14 ++-- .../read/DeprioritizedNearest.json | 63 ++++++++++++++ .../read/DeprioritizedNearest.yml | 26 ++++++ .../read/DeprioritizedPrimary.json | 40 +++++++++ .../read/DeprioritizedPrimary.yml | 22 +++++ .../read/DeprioritizedPrimaryPreferred.json | 63 ++++++++++++++ .../read/DeprioritizedPrimaryPreferred.yml | 26 ++++++ .../read/DeprioritizedSecondary.json | 63 ++++++++++++++ .../read/DeprioritizedSecondary.yml | 26 ++++++ .../read/DeprioritizedSecondaryPreferred.json | 63 ++++++++++++++ .../read/DeprioritizedSecondaryPreferred.yml | 26 ++++++ .../read/DeprioritizedNearest.json | 78 +++++++++++++++++ .../read/DeprioritizedNearest.yml | 33 ++++++++ .../read/DeprioritizedPrimary.json | 49 +++++++++++ .../read/DeprioritizedPrimary.yml | 28 +++++++ .../read/DeprioritizedPrimaryPreferred.json | 84 +++++++++++++++++++ .../read/DeprioritizedPrimaryPreferred.yml | 34 ++++++++ .../read/DeprioritizedSecondary.json | 62 ++++++++++++++ .../read/DeprioritizedSecondary.yml | 31 +++++++ .../read/DeprioritizedSecondaryPreferred.json | 78 +++++++++++++++++ .../read/DeprioritizedSecondaryPreferred.yml | 33 ++++++++ .../DeprioritizedSecondaryPreferred.json | 54 ++++++++++++ .../write/DeprioritizedSecondaryPreferred.yml | 28 +++++++ .../Sharded/read/DeprioritizedNearest.json | 47 +++++++++++ .../Sharded/read/DeprioritizedNearest.yml | 22 +++++ .../Sharded/read/DeprioritizedPrimary.json | 43 ++++++++++ .../Sharded/read/DeprioritizedPrimary.yml | 20 +++++ .../read/DeprioritizedPrimaryPreferred.json | 48 +++++++++++ .../read/DeprioritizedPrimaryPreferred.yml | 22 +++++ .../Sharded/read/DeprioritizedSecondary.json | 48 +++++++++++ .../Sharded/read/DeprioritizedSecondary.yml | 22 +++++ .../read/DeprioritizedSecondaryPreferred.json | 48 +++++++++++ .../read/DeprioritizedSecondaryPreferred.yml | 22 +++++ .../Sharded/write/DeprioritizedNearest.json | 47 +++++++++++ .../Sharded/write/DeprioritizedNearest.yml | 22 +++++ .../Sharded/write/DeprioritizedPrimary.json | 43 ++++++++++ .../Sharded/write/DeprioritizedPrimary.yml | 20 +++++ .../write/DeprioritizedPrimaryPreferred.json | 48 +++++++++++ .../write/DeprioritizedPrimaryPreferred.yml | 22 +++++ .../Sharded/write/DeprioritizedSecondary.json | 48 +++++++++++ .../Sharded/write/DeprioritizedSecondary.yml | 22 +++++ .../DeprioritizedSecondaryPreferred.json | 48 +++++++++++ .../write/DeprioritizedSecondaryPreferred.yml | 22 +++++ .../Single/read/Deprioritized.json | 54 ++++++++++++ .../Single/read/Deprioritized.yml | 20 +++++ .../Single/write/Deprioritized.json | 54 ++++++++++++ .../Single/write/Deprioritized.yml | 20 +++++ 50 files changed, 1859 insertions(+), 15 deletions(-) create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedNearest.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedNearest.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedNearest.json create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedNearest.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.json create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.json create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedNearest.json create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedNearest.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.json create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.json create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.yml create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/Single/read/Deprioritized.json create mode 100644 source/server-selection/tests/server_selection/Single/read/Deprioritized.yml create mode 100644 source/server-selection/tests/server_selection/Single/write/Deprioritized.json create mode 100644 source/server-selection/tests/server_selection/Single/write/Deprioritized.yml diff --git a/source/logging/logging.md b/source/logging/logging.md index 6f7c36c200..8971dbcde7 100644 --- a/source/logging/logging.md +++ b/source/logging/logging.md @@ -95,7 +95,7 @@ Drivers MUST support configuring where log messages should be output, including > - If the value is "stdout" (case-insensitive), log to stdout. > - If the value is "stderr" (case-insensitive), log to stderr. > - Else, if direct logging to files is supported, log to a file at the specified path. If the file already exists, it - > MUST be appended to. + > MUST be appended to. > > If the variable is not provided or is set to an invalid value (which could be invalid for any reason, e.g. the path > does not exist or is not writeable), the driver MUST log to stderr and the driver MAY attempt to warn the user about diff --git a/source/retryable-reads/retryable-reads.md b/source/retryable-reads/retryable-reads.md index d715f774ef..c47f745c8f 100644 --- a/source/retryable-reads/retryable-reads.md +++ b/source/retryable-reads/retryable-reads.md @@ -207,8 +207,8 @@ capture this original retryable error. Drivers should then proceed with selectin ###### 3a. Selecting the server for retry -In a sharded cluster, the server on which the operation failed MUST be provided to the server selection mechanism as a -deprioritized server. +The server on which the operation failed MUST be provided to the server selection mechanism as a member of the +deprioritized server list. If the driver cannot select a server for a retry attempt or the newly selected server does not support retryable reads, retrying is not possible and drivers MUST raise the previous retryable error. In both cases, the caller is able to infer @@ -294,7 +294,7 @@ function executeRetryableRead(command, session) { } else { // If a previous attempt was made, deprioritize the previous server // where the command failed. - deprioritizedServers = [ previousServer ]; + deprioritizedServers.push(previousServer); server = selectServer(deprioritizedServers); } } catch (ServerSelectionException exception) { diff --git a/source/retryable-writes/retryable-writes.md b/source/retryable-writes/retryable-writes.md index 609de18b92..270113ff34 100644 --- a/source/retryable-writes/retryable-writes.md +++ b/source/retryable-writes/retryable-writes.md @@ -317,8 +317,8 @@ Drivers MUST then retry the operation as many times as necessary until any one o - CSOT is not enabled and one retry was attempted. -For each retry attempt, drivers MUST select a writable server. In a sharded cluster, the server on which the operation -failed MUST be provided to the server selection mechanism as a deprioritized server. +For each retry attempt, drivers MUST select a writable server. The server on which the operation failed MUST be provided +to the server selection mechanism as a member of the deprioritized server list. If the driver cannot select a server for a retry attempt or the selected server does not support retryable writes, retrying is not possible and drivers MUST raise the retryable error from the previous attempt. In both cases, the caller @@ -418,13 +418,13 @@ function executeRetryableWrite(command, session) { } /* - * We try to select server that is not the one that failed by passing the - * failed server as a deprioritized server. + * We try to select a server that has not already failed by adding the + * failed server to the passed list of deprioritized servers. * If we cannot select a writable server, do not proceed with retrying and * throw the previous error. The caller can then infer that an attempt was * made and failed. */ try { - deprioritizedServers = [ server ]; + deprioritizedServers.push(server); server = selectServer("writable", deprioritizedServers); } catch (Exception ignoredError) { throw previousError; diff --git a/source/server-selection/server-selection.md b/source/server-selection/server-selection.md index 6d65643f0f..4960930535 100644 --- a/source/server-selection/server-selection.md +++ b/source/server-selection/server-selection.md @@ -708,9 +708,8 @@ For multi-threaded clients, the server selection algorithm is as follows: ["Server selection started" message](#server-selection-started-message). 2. If the topology wire version is invalid, raise an error and log a ["Server selection failed" message](#server-selection-failed-message). -3. Find suitable servers by topology type and operation type. If a list of deprioritized servers is provided, and the - topology is a sharded cluster, these servers should be selected only if there are no other suitable servers. The - server selection algorithm MUST ignore the deprioritized servers if the topology is not a sharded cluster. +3. Find suitable servers by topology type and operation type. If a list of deprioritized servers is provided, these + servers MUST be selected only if there are no other suitable servers. 4. Filter the suitable servers by calling the optional, application-provided server selector. 5. If there are any suitable servers, filter them according to [Filtering suitable servers based on the latency window](#filtering-suitable-servers-based-on-the-latency-window) @@ -756,9 +755,9 @@ Therefore, for single-threaded clients, the server selection algorithm is as fol longer stale) 5. If the topology wire version is invalid, raise an error and log a ["Server selection failed" message](#server-selection-failed-message). -6. Find suitable servers by topology type and operation type. If a list of deprioritized servers is provided, and the - topology is a sharded cluster, these servers should be selected only if there are no other suitable servers. The - server selection algorithm MUST ignore the deprioritized servers if the topology is not a sharded cluster. +6. Find suitable servers by topology type and operation type. If a list of deprioritized servers is provided, these + servers MUST be selected only if there are no other suitable servers. Read and write preferences MUST only be + applied after the deprioritized servers are filtered out, if present. 7. Filter the suitable servers by calling the optional, application-provided server selector. 8. If there are any suitable servers, filter them according to [Filtering suitable servers based on the latency window](#filtering-suitable-servers-based-on-the-latency-window) @@ -1614,6 +1613,9 @@ maxStalenessSeconds first, then tag_sets, and select Node 2. ## Changelog +- 2025-12-04: Require server deprioritization for all topology types and clarify the order of server candidate + filtering. + - 2015-06-26: Updated single-threaded selection logic with "stale" and serverSelectionTryOnce. - 2015-08-10: Updated single-threaded selection logic to ensure a scan always happens at least once under diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.json new file mode 100644 index 0000000000..464e542c54 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.json @@ -0,0 +1,63 @@ +{ + "topology_description": { + "type": "ReplicaSetNoPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "Nearest", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "in_latency_window": [ + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] +} + diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.yml b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.yml new file mode 100644 index 0000000000..9297b98a32 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.yml @@ -0,0 +1,26 @@ +topology_description: + type: ReplicaSetNoPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 100 + type: RSSecondary + tags: + data_center: nyc +operation: read +read_preference: + mode: Nearest + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.json new file mode 100644 index 0000000000..4726045de8 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.json @@ -0,0 +1,40 @@ +{ + "topology_description": { + "type": "ReplicaSetNoPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "Primary" + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [], + "in_latency_window": [] +} + diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.yml b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.yml new file mode 100644 index 0000000000..6d29358f3c --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.yml @@ -0,0 +1,22 @@ +topology_description: + type: ReplicaSetNoPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 100 + type: RSSecondary + tags: + data_center: nyc +operation: read +read_preference: + mode: Primary +deprioritized_servers: +- *1 +suitable_servers: [] +in_latency_window: [] diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.json new file mode 100644 index 0000000000..ef9444e595 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.json @@ -0,0 +1,63 @@ +{ + "topology_description": { + "type": "ReplicaSetNoPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "PrimaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "in_latency_window": [ + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] +} + diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.yml new file mode 100644 index 0000000000..cb08766a3d --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.yml @@ -0,0 +1,26 @@ +topology_description: + type: ReplicaSetNoPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 100 + type: RSSecondary + tags: + data_center: nyc +operation: read +read_preference: + mode: PrimaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.json new file mode 100644 index 0000000000..fbd5456ad6 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.json @@ -0,0 +1,63 @@ +{ + "topology_description": { + "type": "ReplicaSetNoPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "Secondary", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "in_latency_window": [ + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] +} + diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.yml b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.yml new file mode 100644 index 0000000000..08ca00c0ab --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.yml @@ -0,0 +1,26 @@ +topology_description: + type: ReplicaSetNoPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 100 + type: RSSecondary + tags: + data_center: nyc +operation: read +read_preference: + mode: Secondary + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.json new file mode 100644 index 0000000000..d8d92261e1 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.json @@ -0,0 +1,63 @@ +{ + "topology_description": { + "type": "ReplicaSetNoPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "SecondaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "in_latency_window": [ + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] +} + diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.yml new file mode 100644 index 0000000000..0ae92459ae --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.yml @@ -0,0 +1,26 @@ +topology_description: + type: ReplicaSetNoPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 100 + type: RSSecondary + tags: + data_center: nyc +operation: read +read_preference: + mode: SecondaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedNearest.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedNearest.json new file mode 100644 index 0000000000..5b9d0fa538 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedNearest.json @@ -0,0 +1,78 @@ +{ + "topology_description": { + "type": "ReplicaSetWithPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 26, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "Nearest", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 26, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "in_latency_window": [ + { + "address": "a:27017", + "avg_rtt_ms": 26, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] +} diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedNearest.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedNearest.yml new file mode 100644 index 0000000000..3dcb9bffdc --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedNearest.yml @@ -0,0 +1,33 @@ +topology_description: + type: ReplicaSetWithPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 100 + type: RSSecondary + tags: + data_center: nyc + - &3 + address: a:27017 + avg_rtt_ms: 26 + type: RSPrimary + tags: + data_center: nyc +operation: read +read_preference: + mode: Nearest + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *3 +- *2 +in_latency_window: +- *3 diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.json new file mode 100644 index 0000000000..5e679d51b0 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.json @@ -0,0 +1,49 @@ +{ + "topology_description": { + "type": "ReplicaSetWithPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "Primary" + }, + "deprioritized_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + ], + "in_latency_window": [ + ] +} diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.yml new file mode 100644 index 0000000000..ae2b9bac79 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.yml @@ -0,0 +1,28 @@ +topology_description: + type: ReplicaSetWithPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &3 + address: a:27017 + avg_rtt_ms: 5 + type: RSPrimary + tags: + data_center: nyc +operation: read +read_preference: + mode: Primary +deprioritized_servers: +- *3 +suitable_servers: [] +in_latency_window: [] diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.json new file mode 100644 index 0000000000..367d19e66d --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.json @@ -0,0 +1,84 @@ +{ + "topology_description": { + "type": "ReplicaSetWithPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "PrimaryPreferred", + "tag_sets": [ + {} + ] + }, + "deprioritized_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "in_latency_window": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] +} diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.yml new file mode 100644 index 0000000000..83551a51bb --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.yml @@ -0,0 +1,34 @@ +topology_description: + type: ReplicaSetWithPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &3 + address: a:27017 + avg_rtt_ms: 5 + type: RSPrimary + tags: + data_center: nyc +operation: read +read_preference: + mode: PrimaryPreferred + tag_sets: + - {} +deprioritized_servers: +- *3 +suitable_servers: +- *1 +- *2 +in_latency_window: +- *1 +- *2 diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json new file mode 100644 index 0000000000..675c9539fe --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json @@ -0,0 +1,62 @@ +{ + "topology_description": { + "type": "ReplicaSetWithPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 26, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "Secondary", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + ], + "in_latency_window": [ + ] +} diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.yml new file mode 100644 index 0000000000..ef75e789ee --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.yml @@ -0,0 +1,31 @@ +topology_description: + type: ReplicaSetWithPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 100 + type: RSSecondary + tags: + data_center: nyc + - &3 + address: a:27017 + avg_rtt_ms: 26 + type: RSPrimary + tags: + data_center: nyc +operation: read +read_preference: + mode: Secondary + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +- *2 +suitable_servers: [] +in_latency_window: [] diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondaryPreferred.json new file mode 100644 index 0000000000..1fd6c654f0 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondaryPreferred.json @@ -0,0 +1,78 @@ +{ + "topology_description": { + "type": "ReplicaSetWithPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "SecondaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ], + "in_latency_window": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] +} diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondaryPreferred.yml new file mode 100644 index 0000000000..1db29405f9 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondaryPreferred.yml @@ -0,0 +1,33 @@ +topology_description: + type: ReplicaSetWithPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 100 + type: RSSecondary + tags: + data_center: nyc + - &3 + address: a:27017 + avg_rtt_ms: 5 + type: RSPrimary + tags: + data_center: nyc +operation: read +read_preference: + mode: SecondaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +- *2 +suitable_servers: +- *3 +in_latency_window: +- *3 diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json new file mode 100644 index 0000000000..aead0a689e --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json @@ -0,0 +1,54 @@ +{ + "topology_description": { + "type": "ReplicaSetWithPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 26, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "write", + "read_preference": { + "mode": "SecondaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 26, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + ], + "in_latency_window": [ + ] +} diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml new file mode 100644 index 0000000000..89eda073d3 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml @@ -0,0 +1,28 @@ +topology_description: + type: ReplicaSetWithPrimary + servers: + - address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - address: c:27017 + avg_rtt_ms: 100 + type: RSSecondary + tags: + data_center: nyc + - &1 + address: a:27017 + avg_rtt_ms: 26 + type: RSPrimary + tags: + data_center: nyc +operation: write +read_preference: + mode: SecondaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: [] +in_latency_window: [] diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedNearest.json b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedNearest.json new file mode 100644 index 0000000000..1aa730cd21 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedNearest.json @@ -0,0 +1,47 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 10, + "type": "Mongos" + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "Nearest", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 10, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 10, + "type": "Mongos" + } + ] +} diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedNearest.yml b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedNearest.yml new file mode 100644 index 0000000000..27fd8fc693 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedNearest.yml @@ -0,0 +1,22 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 10 + type: Mongos +operation: read +read_preference: + mode: Nearest + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.json b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.json new file mode 100644 index 0000000000..0017e28a46 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.json @@ -0,0 +1,43 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "Primary" + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] +} + diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.yml b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.yml new file mode 100644 index 0000000000..a7bfee07d8 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.yml @@ -0,0 +1,20 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 5 + type: Mongos +operation: read +read_preference: + mode: Primary +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.json b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.json new file mode 100644 index 0000000000..7540492b4d --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.json @@ -0,0 +1,48 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "PrimaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] +} + diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.yml b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.yml new file mode 100644 index 0000000000..3452acdeff --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.yml @@ -0,0 +1,22 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 5 + type: Mongos +operation: read +read_preference: + mode: PrimaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.json b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.json new file mode 100644 index 0000000000..a476695d06 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.json @@ -0,0 +1,48 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "Secondary", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] +} + diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.yml b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.yml new file mode 100644 index 0000000000..5db7667238 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.yml @@ -0,0 +1,22 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 5 + type: Mongos +operation: read +read_preference: + mode: Secondary + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.json new file mode 100644 index 0000000000..effca47d2d --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.json @@ -0,0 +1,48 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "SecondaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] +} + diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.yml b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.yml new file mode 100644 index 0000000000..a07e44b55f --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.yml @@ -0,0 +1,22 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 5 + type: Mongos +operation: read +read_preference: + mode: SecondaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedNearest.json b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedNearest.json new file mode 100644 index 0000000000..5cc2cc5477 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedNearest.json @@ -0,0 +1,47 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 10, + "type": "Mongos" + } + ] + }, + "operation": "write", + "read_preference": { + "mode": "Nearest", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 10, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 10, + "type": "Mongos" + } + ] +} diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedNearest.yml b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedNearest.yml new file mode 100644 index 0000000000..af8ca190d6 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedNearest.yml @@ -0,0 +1,22 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 10 + type: Mongos +operation: write +read_preference: + mode: Nearest + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.json b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.json new file mode 100644 index 0000000000..faae97e51f --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.json @@ -0,0 +1,43 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] + }, + "operation": "write", + "read_preference": { + "mode": "Primary" + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] +} + diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.yml b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.yml new file mode 100644 index 0000000000..7fc405c3f2 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.yml @@ -0,0 +1,20 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 5 + type: Mongos +operation: write +read_preference: + mode: Primary +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.json b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.json new file mode 100644 index 0000000000..3754630246 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.json @@ -0,0 +1,48 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] + }, + "operation": "write", + "read_preference": { + "mode": "PrimaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] +} + diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.yml b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.yml new file mode 100644 index 0000000000..cf2359cc44 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.yml @@ -0,0 +1,22 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 5 + type: Mongos +operation: write +read_preference: + mode: PrimaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.json b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.json new file mode 100644 index 0000000000..905c8df90a --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.json @@ -0,0 +1,48 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] + }, + "operation": "write", + "read_preference": { + "mode": "Secondary", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] +} + diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.yml b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.yml new file mode 100644 index 0000000000..06888b0bb7 --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.yml @@ -0,0 +1,22 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 5 + type: Mongos +operation: write +read_preference: + mode: Secondary + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.json new file mode 100644 index 0000000000..47e55ca20d --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.json @@ -0,0 +1,48 @@ +{ + "topology_description": { + "type": "Sharded", + "servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + }, + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] + }, + "operation": "write", + "read_preference": { + "mode": "SecondaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "g:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "suitable_servers": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ], + "in_latency_window": [ + { + "address": "h:27017", + "avg_rtt_ms": 5, + "type": "Mongos" + } + ] +} + diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.yml b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.yml new file mode 100644 index 0000000000..8c1abf2cec --- /dev/null +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.yml @@ -0,0 +1,22 @@ +topology_description: + type: Sharded + servers: + - &1 + address: g:27017 + avg_rtt_ms: 5 + type: Mongos + - &2 + address: h:27017 + avg_rtt_ms: 5 + type: Mongos +operation: write +read_preference: + mode: SecondaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *2 +in_latency_window: +- *2 diff --git a/source/server-selection/tests/server_selection/Single/read/Deprioritized.json b/source/server-selection/tests/server_selection/Single/read/Deprioritized.json new file mode 100644 index 0000000000..c76fc6c771 --- /dev/null +++ b/source/server-selection/tests/server_selection/Single/read/Deprioritized.json @@ -0,0 +1,54 @@ +{ + "topology_description": { + "type": "Single", + "servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "Standalone", + "tags": { + "data_center": "dc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "SecondaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "Standalone", + "tags": { + "data_center": "dc" + } + } + ], + "suitable_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "Standalone", + "tags": { + "data_center": "dc" + } + } + ], + "in_latency_window": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "Standalone", + "tags": { + "data_center": "dc" + } + } + ] +} diff --git a/source/server-selection/tests/server_selection/Single/read/Deprioritized.yml b/source/server-selection/tests/server_selection/Single/read/Deprioritized.yml new file mode 100644 index 0000000000..463a7a5535 --- /dev/null +++ b/source/server-selection/tests/server_selection/Single/read/Deprioritized.yml @@ -0,0 +1,20 @@ +topology_description: + type: Single + servers: + - &1 + address: a:27017 + avg_rtt_ms: 5 + type: Standalone + tags: + data_center: dc +operation: read +read_preference: + mode: SecondaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *1 +in_latency_window: +- *1 diff --git a/source/server-selection/tests/server_selection/Single/write/Deprioritized.json b/source/server-selection/tests/server_selection/Single/write/Deprioritized.json new file mode 100644 index 0000000000..099076f2da --- /dev/null +++ b/source/server-selection/tests/server_selection/Single/write/Deprioritized.json @@ -0,0 +1,54 @@ +{ + "topology_description": { + "type": "Single", + "servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "Standalone", + "tags": { + "data_center": "dc" + } + } + ] + }, + "operation": "write", + "read_preference": { + "mode": "SecondaryPreferred", + "tag_sets": [ + { + "data_center": "nyc" + } + ] + }, + "deprioritized_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "Standalone", + "tags": { + "data_center": "dc" + } + } + ], + "suitable_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "Standalone", + "tags": { + "data_center": "dc" + } + } + ], + "in_latency_window": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "Standalone", + "tags": { + "data_center": "dc" + } + } + ] +} diff --git a/source/server-selection/tests/server_selection/Single/write/Deprioritized.yml b/source/server-selection/tests/server_selection/Single/write/Deprioritized.yml new file mode 100644 index 0000000000..08780151c9 --- /dev/null +++ b/source/server-selection/tests/server_selection/Single/write/Deprioritized.yml @@ -0,0 +1,20 @@ +topology_description: + type: Single + servers: + - &1 + address: a:27017 + avg_rtt_ms: 5 + type: Standalone + tags: + data_center: dc +operation: write +read_preference: + mode: SecondaryPreferred + tag_sets: + - data_center: nyc +deprioritized_servers: +- *1 +suitable_servers: +- *1 +in_latency_window: +- *1 From 8092cc054599b8a852dc2d1252a51ff9ee42fd62 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Mon, 8 Dec 2025 14:48:04 -0500 Subject: [PATCH 02/12] Linting --- source/retryable-reads/retryable-reads.md | 2 ++ source/retryable-writes/retryable-writes.md | 2 ++ source/server-selection/server-selection.md | 5 +++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/source/retryable-reads/retryable-reads.md b/source/retryable-reads/retryable-reads.md index c47f745c8f..d3ceb9dd5a 100644 --- a/source/retryable-reads/retryable-reads.md +++ b/source/retryable-reads/retryable-reads.md @@ -547,6 +547,8 @@ any customers experiencing degraded performance can simply disable `retryableRea ## Changelog +- 2026-12-08: Clarified that server deprioritization during retries must use a list. + - 2024-04-30: Migrated from reStructuredText to Markdown. - 2023-12-05: Add that any server information associated with retryable exceptions MUST reflect the originating server, diff --git a/source/retryable-writes/retryable-writes.md b/source/retryable-writes/retryable-writes.md index 270113ff34..c5684d561b 100644 --- a/source/retryable-writes/retryable-writes.md +++ b/source/retryable-writes/retryable-writes.md @@ -680,6 +680,8 @@ retryWrites is not true would be inconsistent with the server and potentially co ## Changelog +- 2026-12-08: Clarified that server deprioritization during retries must use a list. + - 2024-05-08: Add guidance for client-level `bulkWrite()` retryability. - 2024-05-02: Migrated from reStructuredText to Markdown. diff --git a/source/server-selection/server-selection.md b/source/server-selection/server-selection.md index 4960930535..4dd2436d32 100644 --- a/source/server-selection/server-selection.md +++ b/source/server-selection/server-selection.md @@ -709,7 +709,8 @@ For multi-threaded clients, the server selection algorithm is as follows: 2. If the topology wire version is invalid, raise an error and log a ["Server selection failed" message](#server-selection-failed-message). 3. Find suitable servers by topology type and operation type. If a list of deprioritized servers is provided, these - servers MUST be selected only if there are no other suitable servers. + servers MUST be selected only if there are no other suitable servers. Read and write preferences MUST only be + applied after the deprioritized servers are filtered out, if present. 4. Filter the suitable servers by calling the optional, application-provided server selector. 5. If there are any suitable servers, filter them according to [Filtering suitable servers based on the latency window](#filtering-suitable-servers-based-on-the-latency-window) @@ -1613,7 +1614,7 @@ maxStalenessSeconds first, then tag_sets, and select Node 2. ## Changelog -- 2025-12-04: Require server deprioritization for all topology types and clarify the order of server candidate +- 2025-12-08: Require server deprioritization for all topology types and clarify the order of server candidate filtering. - 2015-06-26: Updated single-threaded selection logic with "stale" and serverSelectionTryOnce. From a20b81ae432ea4483cb0c0afdd1f334261ce495b Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Mon, 8 Dec 2025 14:55:21 -0500 Subject: [PATCH 03/12] More linting --- source/logging/logging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/logging/logging.md b/source/logging/logging.md index 8971dbcde7..3bfcd45e93 100644 --- a/source/logging/logging.md +++ b/source/logging/logging.md @@ -95,7 +95,7 @@ Drivers MUST support configuring where log messages should be output, including > - If the value is "stdout" (case-insensitive), log to stdout. > - If the value is "stderr" (case-insensitive), log to stderr. > - Else, if direct logging to files is supported, log to a file at the specified path. If the file already exists, it - > MUST be appended to. + > MUST be appended to. > > If the variable is not provided or is set to an invalid value (which could be invalid for any reason, e.g. the path > does not exist or is not writeable), the driver MUST log to stderr and the driver MAY attempt to warn the user about From 4a1bcdc0663eff7003c3207cb3c30a2ac5d87e09 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Mon, 8 Dec 2025 14:58:44 -0500 Subject: [PATCH 04/12] More linting --- source/logging/logging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/logging/logging.md b/source/logging/logging.md index 3bfcd45e93..6f7c36c200 100644 --- a/source/logging/logging.md +++ b/source/logging/logging.md @@ -95,7 +95,7 @@ Drivers MUST support configuring where log messages should be output, including > - If the value is "stdout" (case-insensitive), log to stdout. > - If the value is "stderr" (case-insensitive), log to stderr. > - Else, if direct logging to files is supported, log to a file at the specified path. If the file already exists, it - > MUST be appended to. + > MUST be appended to. > > If the variable is not provided or is set to an invalid value (which could be invalid for any reason, e.g. the path > does not exist or is not writeable), the driver MUST log to stderr and the driver MAY attempt to warn the user about From c5f04fa546ad7de62578b9f9c29052d8e31bc184 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Tue, 9 Dec 2025 13:19:17 -0500 Subject: [PATCH 05/12] Add tests to verify correct behavior for preferred when all servers are deprioritized --- .../DeprioritizedAllPrimaryPreferred.json | 84 +++++++++++++++ .../read/DeprioritizedAllPrimaryPreferred.yml | 34 ++++++ .../DeprioritizedAllSecondaryPreferred.json | 100 ++++++++++++++++++ .../DeprioritizedAllSecondaryPreferred.yml | 36 +++++++ 4 files changed, 254 insertions(+) create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.yml create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.json create mode 100644 source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.yml diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.json new file mode 100644 index 0000000000..095537ba1a --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.json @@ -0,0 +1,84 @@ +{ + "topology_description": { + "type": "ReplicaSetWithPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "PrimaryPreferred", + "tag_sets": [ + {} + ] + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ], + "in_latency_window": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] +} diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.yml new file mode 100644 index 0000000000..f63605889e --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.yml @@ -0,0 +1,34 @@ +topology_description: + type: ReplicaSetWithPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &3 + address: a:27017 + avg_rtt_ms: 5 + type: RSPrimary + tags: + data_center: nyc +operation: read +read_preference: + mode: PrimaryPreferred + tag_sets: + - {} +deprioritized_servers: +- *1 +- *2 +- *3 +suitable_servers: +- *3 +in_latency_window: +- *3 diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.json new file mode 100644 index 0000000000..b29ba2bc80 --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.json @@ -0,0 +1,100 @@ +{ + "topology_description": { + "type": "ReplicaSetWithPrimary", + "servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ] + }, + "operation": "read", + "read_preference": { + "mode": "SecondaryPreferred", + "tag_sets": [ + {} + ] + }, + "deprioritized_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } + ], + "suitable_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ], + "in_latency_window": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } + ] +} diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.yml new file mode 100644 index 0000000000..37e9e055ca --- /dev/null +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.yml @@ -0,0 +1,36 @@ +topology_description: + type: ReplicaSetWithPrimary + servers: + - &1 + address: b:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &2 + address: c:27017 + avg_rtt_ms: 5 + type: RSSecondary + tags: + data_center: nyc + - &3 + address: a:27017 + avg_rtt_ms: 5 + type: RSPrimary + tags: + data_center: nyc +operation: read +read_preference: + mode: SecondaryPreferred + tag_sets: + - {} +deprioritized_servers: +- *1 +- *2 +- *3 +suitable_servers: +- *1 +- *2 +in_latency_window: +- *1 +- *2 From 56711a176ca8bb9a97ddb4f159bbc7df931d6ef2 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Tue, 9 Dec 2025 15:04:14 -0500 Subject: [PATCH 06/12] Address review --- .../server-selection-tests.md | 12 ++++++---- source/server-selection/server-selection.md | 14 ++++++----- .../read/DeprioritizedPrimary.json | 16 +++++++++++++ .../read/DeprioritizedPrimary.yml | 6 +++-- .../read/DeprioritizedSecondary.json | 24 +++++++++++++++++++ .../read/DeprioritizedSecondary.yml | 7 ++++-- .../DeprioritizedSecondaryPreferred.json | 16 +++++++++++++ .../write/DeprioritizedSecondaryPreferred.yml | 6 +++-- 8 files changed, 85 insertions(+), 16 deletions(-) diff --git a/source/server-selection/server-selection-tests.md b/source/server-selection/server-selection-tests.md index 8b07b1da13..eb055242a9 100644 --- a/source/server-selection/server-selection-tests.md +++ b/source/server-selection/server-selection-tests.md @@ -40,15 +40,19 @@ The following test cases can be found in YAML form in the "tests" directory. Eac representing a set of servers, a ReadPreference document, and sets of servers returned at various stages of the server selection process. These sets are described below. Note that it is not required to test for correctness at every step. -| Test Case | Description | -| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -| `suitable_servers` | the set of servers matching all server selection logic. | -| `in_latency_window` | the subset of `suitable_servers` that falls within the allowable latency window (required). NOTE: tests use the default localThresholdMS of 15 ms. | +| Test Case | Description | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `suitable_servers` | the set of servers matching all server selection logic. | +| `in_latency_window` | the subset of `suitable_servers` that falls within the allowable latency window (required). NOTE: tests use the default localThresholdMS of 15 ms. | +| `deprioritized_servers` | the set of servers that are deprioritized and must only be selected if no other suitable server exists. | Drivers implementing server selection MUST test that their implementations correctly return **one** of the servers in `in_latency_window`. Drivers SHOULD test against the full set of servers in `in_latency_window` and against `suitable_servers` if possible. +For tests containing `deprioritized_servers`, drivers MUST pass the given list of deprioritized servers to each server +selection call. + ### Topology Type Single - The single server is always selected. diff --git a/source/server-selection/server-selection.md b/source/server-selection/server-selection.md index 4dd2436d32..8463ec1a8c 100644 --- a/source/server-selection/server-selection.md +++ b/source/server-selection/server-selection.md @@ -708,9 +708,10 @@ For multi-threaded clients, the server selection algorithm is as follows: ["Server selection started" message](#server-selection-started-message). 2. If the topology wire version is invalid, raise an error and log a ["Server selection failed" message](#server-selection-failed-message). -3. Find suitable servers by topology type and operation type. If a list of deprioritized servers is provided, these - servers MUST be selected only if there are no other suitable servers. Read and write preferences MUST only be - applied after the deprioritized servers are filtered out, if present. +3. Find suitable servers as follows: + - Filter out any deprioritized servers. + - Find suitable servers from the filtered list by topology type and operation type. + - If there are no suitable servers, perform the previous step again without filtering out deprioritized servers. 4. Filter the suitable servers by calling the optional, application-provided server selector. 5. If there are any suitable servers, filter them according to [Filtering suitable servers based on the latency window](#filtering-suitable-servers-based-on-the-latency-window) @@ -756,9 +757,10 @@ Therefore, for single-threaded clients, the server selection algorithm is as fol longer stale) 5. If the topology wire version is invalid, raise an error and log a ["Server selection failed" message](#server-selection-failed-message). -6. Find suitable servers by topology type and operation type. If a list of deprioritized servers is provided, these - servers MUST be selected only if there are no other suitable servers. Read and write preferences MUST only be - applied after the deprioritized servers are filtered out, if present. +6. Find suitable servers as follows: + - Filter out any deprioritized servers. + - Find suitable servers from the filtered list by topology type and operation type. + - If there are no suitable servers, perform the previous step again without filtering out deprioritized servers. 7. Filter the suitable servers by calling the optional, application-provided server selector. 8. If there are any suitable servers, filter them according to [Filtering suitable servers based on the latency window](#filtering-suitable-servers-based-on-the-latency-window) diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.json index 5e679d51b0..a1ef5b200f 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.json +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.json @@ -43,7 +43,23 @@ } ], "suitable_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } ], "in_latency_window": [ + { + "address": "a:27017", + "avg_rtt_ms": 5, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } ] } diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.yml index ae2b9bac79..a4c09ba3d4 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.yml +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimary.yml @@ -24,5 +24,7 @@ read_preference: mode: Primary deprioritized_servers: - *3 -suitable_servers: [] -in_latency_window: [] +suitable_servers: +- *3 +in_latency_window: +- *3 diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json index 675c9539fe..32080807a1 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json @@ -56,7 +56,31 @@ } ], "suitable_servers": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + }, + { + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } ], "in_latency_window": [ + { + "address": "b:27017", + "avg_rtt_ms": 5, + "type": "RSSecondary", + "tags": { + "data_center": "nyc" + } + } ] } diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.yml index ef75e789ee..cfcedf3a57 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.yml +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.yml @@ -27,5 +27,8 @@ read_preference: deprioritized_servers: - *1 - *2 -suitable_servers: [] -in_latency_window: [] +suitable_servers: +- *1 +- *2 +in_latency_window: +- *1 diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json index aead0a689e..0f3642aa20 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json @@ -48,7 +48,23 @@ } ], "suitable_servers": [ + { + "address": "a:27017", + "avg_rtt_ms": 26, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } ], "in_latency_window": [ + { + "address": "a:27017", + "avg_rtt_ms": 26, + "type": "RSPrimary", + "tags": { + "data_center": "nyc" + } + } ] } diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml index 89eda073d3..cb0d7acbb3 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml @@ -24,5 +24,7 @@ read_preference: - data_center: nyc deprioritized_servers: - *1 -suitable_servers: [] -in_latency_window: [] +suitable_servers: +- *3 +in_latency_window: +- *3 From 3ddbfd827cdae5b3c0df3bd45a852367e169e88c Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Wed, 10 Dec 2025 13:20:21 -0500 Subject: [PATCH 07/12] Track deprioritized addresses not servers --- source/server-selection/server-selection.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/server-selection/server-selection.md b/source/server-selection/server-selection.md index 8463ec1a8c..f6fb99852d 100644 --- a/source/server-selection/server-selection.md +++ b/source/server-selection/server-selection.md @@ -709,7 +709,7 @@ For multi-threaded clients, the server selection algorithm is as follows: 2. If the topology wire version is invalid, raise an error and log a ["Server selection failed" message](#server-selection-failed-message). 3. Find suitable servers as follows: - - Filter out any deprioritized servers. + - Filter out any deprioritized server addresses. - Find suitable servers from the filtered list by topology type and operation type. - If there are no suitable servers, perform the previous step again without filtering out deprioritized servers. 4. Filter the suitable servers by calling the optional, application-provided server selector. @@ -758,7 +758,7 @@ Therefore, for single-threaded clients, the server selection algorithm is as fol 5. If the topology wire version is invalid, raise an error and log a ["Server selection failed" message](#server-selection-failed-message). 6. Find suitable servers as follows: - - Filter out any deprioritized servers. + - Filter out any deprioritized server addresses. - Find suitable servers from the filtered list by topology type and operation type. - If there are no suitable servers, perform the previous step again without filtering out deprioritized servers. 7. Filter the suitable servers by calling the optional, application-provided server selector. From 4282bfa46626251d049b15553f5707e53a747511 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Wed, 10 Dec 2025 15:03:15 -0500 Subject: [PATCH 08/12] Adress bailey review --- source/retryable-reads/retryable-reads.md | 10 +++++----- source/retryable-writes/retryable-writes.md | 8 ++++---- source/server-selection/server-selection.md | 10 ++++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/source/retryable-reads/retryable-reads.md b/source/retryable-reads/retryable-reads.md index d3ceb9dd5a..945549dcd3 100644 --- a/source/retryable-reads/retryable-reads.md +++ b/source/retryable-reads/retryable-reads.md @@ -207,8 +207,8 @@ capture this original retryable error. Drivers should then proceed with selectin ###### 3a. Selecting the server for retry -The server on which the operation failed MUST be provided to the server selection mechanism as a member of the -deprioritized server list. +The server address on which the operation failed MUST be provided to the server selection mechanism as a member of the +deprioritized server address list. If the driver cannot select a server for a retry attempt or the newly selected server does not support retryable reads, retrying is not possible and drivers MUST raise the previous retryable error. In both cases, the caller is able to infer @@ -292,9 +292,9 @@ function executeRetryableRead(command, session) { if (previousServer == null) { server = selectServer(); } else { - // If a previous attempt was made, deprioritize the previous server + // If a previous attempt was made, deprioritize the previous server address // where the command failed. - deprioritizedServers.push(previousServer); + deprioritizedServers.push(previousServer.address); server = selectServer(deprioritizedServers); } } catch (ServerSelectionException exception) { @@ -547,7 +547,7 @@ any customers experiencing degraded performance can simply disable `retryableRea ## Changelog -- 2026-12-08: Clarified that server deprioritization during retries must use a list. +- 2026-12-08: Clarified that server deprioritization during retries must use a list of server addresses. - 2024-04-30: Migrated from reStructuredText to Markdown. diff --git a/source/retryable-writes/retryable-writes.md b/source/retryable-writes/retryable-writes.md index c5684d561b..f3e0491bc9 100644 --- a/source/retryable-writes/retryable-writes.md +++ b/source/retryable-writes/retryable-writes.md @@ -317,8 +317,8 @@ Drivers MUST then retry the operation as many times as necessary until any one o - CSOT is not enabled and one retry was attempted. -For each retry attempt, drivers MUST select a writable server. The server on which the operation failed MUST be provided -to the server selection mechanism as a member of the deprioritized server list. +For each retry attempt, drivers MUST select a writable server. The server address on which the operation failed MUST be +provided to the server selection mechanism as a member of the deprioritized server address list. If the driver cannot select a server for a retry attempt or the selected server does not support retryable writes, retrying is not possible and drivers MUST raise the retryable error from the previous attempt. In both cases, the caller @@ -424,7 +424,7 @@ function executeRetryableWrite(command, session) { * throw the previous error. The caller can then infer that an attempt was * made and failed. */ try { - deprioritizedServers.push(server); + deprioritizedServers.push(server.address); server = selectServer("writable", deprioritizedServers); } catch (Exception ignoredError) { throw previousError; @@ -680,7 +680,7 @@ retryWrites is not true would be inconsistent with the server and potentially co ## Changelog -- 2026-12-08: Clarified that server deprioritization during retries must use a list. +- 2026-12-08: Clarified that server deprioritization during retries must use a list of server addresses. - 2024-05-08: Add guidance for client-level `bulkWrite()` retryability. diff --git a/source/server-selection/server-selection.md b/source/server-selection/server-selection.md index f6fb99852d..bd589ab307 100644 --- a/source/server-selection/server-selection.md +++ b/source/server-selection/server-selection.md @@ -1607,6 +1607,16 @@ filter it out because it is too stale, and be left with no eligible servers. The user's intent in specifying two tag sets was to fall back to the second set if needed, so we filter by maxStalenessSeconds first, then tag_sets, and select Node 2. +### Why does server deprioritization use only server addresses and not ServerDescription objects? + +A server's address is the minimum identifying attribute that stays constant for across topology changes. Drivers create +new ServerDescription objects on each topology change, and since ServerDescription objects check multiple attributes to +determine equality comparisons, a deprioritized server could become non-equal to itself after a change and therefore +incorrectly be considered suitable for a retry operation. + +By using addresses, we ensure that once a server is marked as deprioritized by an operation, it cannot be used again for +a retry on that operation unless there are no other suitable servers. + ## References - [Server Discovery and Monitoring](../server-discovery-and-monitoring/server-discovery-and-monitoring.md) specification From 11100fa4d26a36ef22ef15b3dee658105a3644c6 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Thu, 11 Dec 2025 10:23:18 -0500 Subject: [PATCH 09/12] Clarify correct deprioritized example and preferred behavior --- source/retryable-reads/retryable-reads.md | 1 + source/retryable-writes/retryable-writes.md | 3 ++- source/server-selection/server-selection.md | 6 ++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/retryable-reads/retryable-reads.md b/source/retryable-reads/retryable-reads.md index 945549dcd3..63837c1a6a 100644 --- a/source/retryable-reads/retryable-reads.md +++ b/source/retryable-reads/retryable-reads.md @@ -284,6 +284,7 @@ function executeRetryableRead(command, session) { Exception previousError = null; retrying = false; Server previousServer = null; + deprioritizedServers = []; while true { if (previousError != null) { retrying = true; diff --git a/source/retryable-writes/retryable-writes.md b/source/retryable-writes/retryable-writes.md index f3e0491bc9..85f81485d8 100644 --- a/source/retryable-writes/retryable-writes.md +++ b/source/retryable-writes/retryable-writes.md @@ -377,6 +377,7 @@ function executeRetryableWrite(command, session) { Exception previousError = null; retrying = false; + deprioritizedServers = []; while true { try { return executeCommand(server, retryableCommand); @@ -419,7 +420,7 @@ function executeRetryableWrite(command, session) { /* * We try to select a server that has not already failed by adding the - * failed server to the passed list of deprioritized servers. + * failed server to the list of deprioritized servers passed to selectServer. * If we cannot select a writable server, do not proceed with retrying and * throw the previous error. The caller can then infer that an attempt was * made and failed. */ diff --git a/source/server-selection/server-selection.md b/source/server-selection/server-selection.md index bd589ab307..555bb859ab 100644 --- a/source/server-selection/server-selection.md +++ b/source/server-selection/server-selection.md @@ -848,10 +848,12 @@ details on each step, and [why is maxStalenessSeconds applied before tag_sets?](#why-is-maxstalenessseconds-applied-before-tag_sets).) If `mode` is 'secondaryPreferred', attempt the selection algorithm with `mode` 'secondary' and the user's -`maxStalenessSeconds` and `tag_sets`. If no server matches, select the primary. +`maxStalenessSeconds` and `tag_sets`. If no server matches, select the primary. Note that if all secondaries are +deprioritized, the primary MUST be selected. If `mode` is 'primaryPreferred', select the primary if it is known, otherwise attempt the selection algorithm with -`mode` 'secondary' and the user's `maxStalenessSeconds` and `tag_sets`. +`mode` 'secondary' and the user's `maxStalenessSeconds` and `tag_sets`. Note that if the primary is deprioritized, a +secondary MUST be selected. For all read preferences modes except 'primary', clients MUST set the `SecondaryOk` wire protocol flag (OP_QUERY) or `$readPreference` global command argument (OP_MSG) to ensure that any suitable server can handle the request. If the From 615ec0e10fc79f546de42282cbdfcc7a90341655 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Thu, 11 Dec 2025 11:03:18 -0500 Subject: [PATCH 10/12] Clarify preferred deprioritization --- source/server-selection/server-selection.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/server-selection/server-selection.md b/source/server-selection/server-selection.md index 555bb859ab..39c2bf3aa4 100644 --- a/source/server-selection/server-selection.md +++ b/source/server-selection/server-selection.md @@ -849,11 +849,11 @@ details on each step, and If `mode` is 'secondaryPreferred', attempt the selection algorithm with `mode` 'secondary' and the user's `maxStalenessSeconds` and `tag_sets`. If no server matches, select the primary. Note that if all secondaries are -deprioritized, the primary MUST be selected. +deprioritized, the primary MUST be selected if it is available. If `mode` is 'primaryPreferred', select the primary if it is known, otherwise attempt the selection algorithm with `mode` 'secondary' and the user's `maxStalenessSeconds` and `tag_sets`. Note that if the primary is deprioritized, a -secondary MUST be selected. +secondary MUST be selected if one is available. For all read preferences modes except 'primary', clients MUST set the `SecondaryOk` wire protocol flag (OP_QUERY) or `$readPreference` global command argument (OP_MSG) to ensure that any suitable server can handle the request. If the From 249dc811c434ea4ab648de60f3e559c055f96f17 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Thu, 11 Dec 2025 13:05:24 -0500 Subject: [PATCH 11/12] Fix JSON --- .../read/DeprioritizedNearest.json | 1 - .../read/DeprioritizedPrimary.json | 1 - .../read/DeprioritizedPrimaryPreferred.json | 1 - .../read/DeprioritizedSecondary.json | 1 - .../read/DeprioritizedSecondaryPreferred.json | 1 - .../read/DeprioritizedAllPrimaryPreferred.json | 2 +- .../read/DeprioritizedAllSecondaryPreferred.json | 2 +- .../read/DeprioritizedPrimaryPreferred.json | 2 +- .../read/DeprioritizedSecondary.json | 2 +- .../write/DeprioritizedSecondaryPreferred.json | 16 ++++++++-------- .../write/DeprioritizedSecondaryPreferred.yml | 15 +++++++-------- .../Sharded/read/DeprioritizedPrimary.json | 1 - .../read/DeprioritizedPrimaryPreferred.json | 1 - .../Sharded/read/DeprioritizedSecondary.json | 1 - .../read/DeprioritizedSecondaryPreferred.json | 1 - .../Sharded/write/DeprioritizedPrimary.json | 1 - .../write/DeprioritizedPrimaryPreferred.json | 1 - .../Sharded/write/DeprioritizedSecondary.json | 1 - .../write/DeprioritizedSecondaryPreferred.json | 1 - 19 files changed, 19 insertions(+), 33 deletions(-) diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.json index 464e542c54..f569c39d6c 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.json +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedNearest.json @@ -60,4 +60,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.json index 4726045de8..8ec76964e9 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.json +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimary.json @@ -37,4 +37,3 @@ "suitable_servers": [], "in_latency_window": [] } - diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.json index ef9444e595..4ab48d0b66 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.json +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedPrimaryPreferred.json @@ -60,4 +60,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.json index fbd5456ad6..202a277487 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.json +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondary.json @@ -60,4 +60,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.json index d8d92261e1..d37e5545da 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.json +++ b/source/server-selection/tests/server_selection/ReplicaSetNoPrimary/read/DeprioritizedSecondaryPreferred.json @@ -60,4 +60,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.json index 095537ba1a..9f415203b3 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.json +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllPrimaryPreferred.json @@ -31,7 +31,7 @@ "operation": "read", "read_preference": { "mode": "PrimaryPreferred", - "tag_sets": [ + "tag_sets": [ {} ] }, diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.json index b29ba2bc80..f8d321b067 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.json +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedAllSecondaryPreferred.json @@ -31,7 +31,7 @@ "operation": "read", "read_preference": { "mode": "SecondaryPreferred", - "tag_sets": [ + "tag_sets": [ {} ] }, diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.json index 367d19e66d..7b6da395c5 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.json +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedPrimaryPreferred.json @@ -31,7 +31,7 @@ "operation": "read", "read_preference": { "mode": "PrimaryPreferred", - "tag_sets": [ + "tag_sets": [ {} ] }, diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json index 32080807a1..f3dc03db09 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/read/DeprioritizedSecondary.json @@ -37,7 +37,7 @@ } ] }, - "deprioritized_servers": [ + "deprioritized_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json index 0f3642aa20..4669ee57d5 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.json @@ -3,25 +3,25 @@ "type": "ReplicaSetWithPrimary", "servers": [ { - "address": "b:27017", - "avg_rtt_ms": 5, - "type": "RSSecondary", + "address": "a:27017", + "avg_rtt_ms": 26, + "type": "RSPrimary", "tags": { "data_center": "nyc" } }, { - "address": "c:27017", - "avg_rtt_ms": 100, + "address": "b:27017", + "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { - "address": "a:27017", - "avg_rtt_ms": 26, - "type": "RSPrimary", + "address": "c:27017", + "avg_rtt_ms": 100, + "type": "RSSecondary", "tags": { "data_center": "nyc" } diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml index cb0d7acbb3..00c2b7978a 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml @@ -1,6 +1,11 @@ topology_description: type: ReplicaSetWithPrimary servers: + - address: a:27017 + avg_rtt_ms: 26 + type: RSPrimary + tags: + data_center: nyc - address: b:27017 avg_rtt_ms: 5 type: RSSecondary @@ -11,12 +16,6 @@ topology_description: type: RSSecondary tags: data_center: nyc - - &1 - address: a:27017 - avg_rtt_ms: 26 - type: RSPrimary - tags: - data_center: nyc operation: write read_preference: mode: SecondaryPreferred @@ -25,6 +24,6 @@ read_preference: deprioritized_servers: - *1 suitable_servers: -- *3 +- *1 in_latency_window: -- *3 +- *1 diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.json b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.json index 0017e28a46..8629c84a2b 100644 --- a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.json +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimary.json @@ -40,4 +40,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.json b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.json index 7540492b4d..800264cfde 100644 --- a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.json +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedPrimaryPreferred.json @@ -45,4 +45,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.json b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.json index a476695d06..42d1e227f1 100644 --- a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.json +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondary.json @@ -45,4 +45,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.json index effca47d2d..eaab0b3af5 100644 --- a/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.json +++ b/source/server-selection/tests/server_selection/Sharded/read/DeprioritizedSecondaryPreferred.json @@ -45,4 +45,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.json b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.json index faae97e51f..a936658939 100644 --- a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.json +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimary.json @@ -40,4 +40,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.json b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.json index 3754630246..5dc3fa292d 100644 --- a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.json +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedPrimaryPreferred.json @@ -45,4 +45,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.json b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.json index 905c8df90a..8b5cc5251c 100644 --- a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.json +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondary.json @@ -45,4 +45,3 @@ } ] } - diff --git a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.json b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.json index 47e55ca20d..dcff289cc2 100644 --- a/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.json +++ b/source/server-selection/tests/server_selection/Sharded/write/DeprioritizedSecondaryPreferred.json @@ -45,4 +45,3 @@ } ] } - From 80c0dd537d53d868f7e41053e164c88b2bbc3bf3 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Mon, 15 Dec 2025 14:22:48 -0500 Subject: [PATCH 12/12] Fix yml --- .../write/DeprioritizedSecondaryPreferred.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml index 00c2b7978a..71521cee62 100644 --- a/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml +++ b/source/server-selection/tests/server_selection/ReplicaSetWithPrimary/write/DeprioritizedSecondaryPreferred.yml @@ -1,11 +1,12 @@ topology_description: type: ReplicaSetWithPrimary servers: - - address: a:27017 + - &1 + address: a:27017 avg_rtt_ms: 26 type: RSPrimary tags: - data_center: nyc + data_center: nyc - address: b:27017 avg_rtt_ms: 5 type: RSSecondary