Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions source/retryable-reads/retryable-reads.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,14 @@ capture this original retryable error. Drivers should then proceed with selectin

###### 3a. Selecting the server for retry

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.
For sharded clusters, 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.

For all other topologies, 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 only if the error is labelled with
`SystemOverloadedError`. All other retryable errors MUST NOT cause the server address to be added to the deprioritized
server address list. This requirement preserves the existing behavior of retryable reads for non-overload errors and
avoids unintended consequences for operations utilizing primaryPreferred and secondaryPreferred read preferences.

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
Expand Down Expand Up @@ -295,7 +301,11 @@ function executeRetryableRead(command, session) {
} else {
// If a previous attempt was made, deprioritize the previous server address
// where the command failed.
deprioritizedServers.push(previousServer.address);
// Sharded clusters deprioritize on all retryable errors.
// Other topologies only deprioritize on overload errors.
if previousServer.isSharded || previousError.hasLabel("SystemOverloadedError") {
deprioritizedServers.push(previousServer.address);
}
server = selectServer(deprioritizedServers);
}
} catch (ServerSelectionException exception) {
Expand Down Expand Up @@ -548,6 +558,8 @@ any customers experiencing degraded performance can simply disable `retryableRea

## Changelog

- 2026-02-19: Clarified that server deprioritization on replica sets only occurs for `SystemOverloadedError` errors.

- 2025-12-08: Clarified that server deprioritization during retries must use a list of server addresses.

- 2024-04-30: Migrated from reStructuredText to Markdown.
Expand Down
66 changes: 66 additions & 0 deletions source/retryable-reads/tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,74 @@ This test MUST be executed against a sharded cluster that supports `retryReads=t

7. Disable the fail point on `s0`.

### 3. Retrying Reads in a Replica Set

These tests will be used to ensure drivers properly retry reads against a replica set.

#### 3.1 Retryable Reads Caused by Overload Errors Are Retried on a Different Replicaset Server When One is Available

This test MUST be executed against a MongoDB 4.4+ replica set that has at least one secondary, supports
`retryReads=true`, and has enabled the `configureFailPoint` command with the `errorLabels` option.

1. Create a client `client` with `retryReads=true`, `readPreference=primaryPreferred`, and command event monitoring
enabled.

2. Configure the following fail point for `client`:

```javascript
{
configureFailPoint: "failCommand",
mode: { times: 1 },
data: {
failCommands: ["find"],
errorLabels: ["RetryableError", "SystemOverloadedError"]
errorCode: 6
}
}
```

3. Reset the command event monitor to clear the failpoint command from its stored events.

4. Execute a `find` command with `client`.

5. Assert that one failed command event and one successful command event occurred.

6. Assert that both events occurred on different servers.

#### 3.2 Retryable Reads Caused by Non-Overload Errors Are Retried on the Same Replicaset Server

This test MUST be executed against a MongoDB 4.4+ replica set that has at least one secondary, supports
`retryReads=true`, and has enabled the `configureFailPoint` command with the `errorLabels` option.

1. Create a client `client` with `retryReads=true`, `readPreference=primaryPreferred`, and command event monitoring
enabled.

2. Configure the following fail point for `client`:

```javascript
{
configureFailPoint: "failCommand",
mode: { times: 1 },
data: {
failCommands: ["find"],
errorLabels: ["RetryableError"]
errorCode: 6
}
}
```

3. Reset the command event monitor to clear the failpoint command from its stored events.

4. Execute a `find` command with `client`.

5. Assert that one failed command event and one successful command event occurred.

6. Assert that both events occurred on the same server.

## Changelog

- 2026-02-19: Add prose tests for retrying against a replica set.

- 2024-04-30: Migrated from reStructuredText to Markdown.

- 2024-03-06: Convert legacy retryable reads tests to unified format.
Expand Down
15 changes: 12 additions & 3 deletions source/retryable-writes/retryable-writes.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,11 @@ 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 address on which the operation failed MUST be
provided to the server selection mechanism as a member of the deprioritized server address list.
For each retry attempt, drivers MUST select a writable server. For sharded clusters, 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. For all other topologies, 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 only if the error is labelled with
`SystemOverloadedError`. This requirement preserves the existing behavior of retryable writes for non-overload errors.

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
Expand Down Expand Up @@ -436,8 +439,12 @@ function executeRetryableWrite(command, session) {
* 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. */
// Sharded clusters deprioritize on all retryable errors.
// Other topologies only deprioritize on overload errors.
try {
deprioritizedServers.push(server.address);
if server.isSharded || previousError.hasLabel("SystemOverloadedError") {
deprioritizedServers.push(server.address);
}
server = selectServer("writable", deprioritizedServers);
} catch (Exception ignoredError) {
throw previousError;
Expand Down Expand Up @@ -693,6 +700,8 @@ retryWrites is not true would be inconsistent with the server and potentially co

## Changelog

- 2026-02-19: Clarified that server deprioritization on replica sets only occurs for `SystemOverloadedError` errors.

- 2026-01-14: Clarify which error to return when more than one error with the `NoWritesPerformed` label is encountered.

- 2025-12-08: Clarified that server deprioritization during retries must use a list of server addresses.
Expand Down
Loading