Skip to content

Commit 4fe6b74

Browse files
runCommand handling
1 parent a00a063 commit 4fe6b74

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

source/client-backpressure/client-backpressure.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ rules:
129129
4. A token can be consumed from the token bucket.
130130
5. The command is a write and [retryWrites](../retryable-writes/retryable-writes.md#retrywrites) is enabled or the
131131
command is a read and [retryReads](../retryable-reads/retryable-reads.md#retryreads) is enabled.
132+
- To retry `runCommand`, both [retryWrites](../retryable-writes/retryable-writes.md#retrywrites) and
133+
[retryReads](../retryable-reads/retryable-reads.md#retryreads) must be enabled. See
134+
[Why must both `retryWrites` and `retryReads` be enabled to retry runCommand?](client-backpressure.md#why-must-both-retrywrites-and-retryreads-be-enabled-to-retry-runcommand)
132135
6. A retry attempt consumes 1 token from the token bucket.
133136
7. If the request is eligible for retry (as outlined in step 5), the client MUST apply exponential backoff according to
134137
the following formula: `backoff = jitter * min(MAX_BACKOFF, BASE_BACKOFF * 2^(attempt - 1))`
@@ -150,6 +153,8 @@ rules:
150153
described in the [retryable reads](../retryable-reads/retryable-reads.md),
151154
[retryable writes](../retryable-writes/retryable-writes.md) and the
152155
[transactions](../transactions/transactions.md) specifications.
156+
- For the purposes of error propagation, `runCommand` is considered a write. See
157+
[Why is runCommand considered a write for error propagation?](#why-is-runcommand-considered-a-write-for-error-propagation)
153158

154159
#### Interaction with Other Retry Policies
155160

@@ -411,6 +416,34 @@ be authenticated until after the authentication workflow has completed and durin
411416
considered authenticated by the server. So, authentication and reauthentication commands will not hit the ingress
412417
operation rate limiter.
413418

419+
### Why must both `retryWrites` and `retryReads` be enabled to retry runCommand?
420+
421+
[`runCommand`](../run-command/run-command.md) is not retryable under the
422+
[retryable reads](../retryable-reads/retryable-reads.md) and [retryable writes](../retryable-writes/retryable-writes.md)
423+
specifications and consequently it was not historically classified as a read or write command.
424+
425+
The most flexible approach would be to inspect the user's command and determine if it is a read or a write. However,
426+
this is problematic for two reasons:
427+
428+
- The runCommand specification specifically forbids drivers from inspecting the user's command.
429+
- `runCommand` is commonly used to execute commands of which the driver has no knowledge and therefore cannot determine
430+
whether it is a read or write.
431+
432+
Another option is to always consider `runCommand` retryable under the overload retry policy, regardless of the setting
433+
of [`retryReads`](../retryable-reads/retryable-reads.md#retryreads) and
434+
[`retryWrites`](../retryable-writes/retryable-writes.md#retrywrites). However, this behavior goes against a user's
435+
expectations: if a user disables both options, they would expect no commands to be retried.
436+
437+
Retrying `runCommand` only when both `retryReads` and `retryWrites` are enabled is a safe default that does not have the
438+
pitfalls of either approach outlined by above:
439+
440+
- This approach does not require drivers to inspect a user's command document.
441+
- This approach will not retry commands if a user has disabled both `retryReads` and `retryWrites`.
442+
443+
Additionally, both `retryReads` and `retryWrites` are enabled by default, so for most users `runCommand` will be
444+
retried. This approach also prevents accidentally retrying a read command when only `retryWrites` is enabled, or
445+
retrying a write command when only `retryReads` is enabled.
446+
414447
## Changelog
415448

416449
- 2026-01-09: Initial version.

0 commit comments

Comments
 (0)