Skip to content

Adds overload retry for not retryable commands - #2048

Draft
vbabanin wants to merge 1 commit into
mongodb:backpressurefrom
vbabanin:support-non-retry-command
Draft

Adds overload retry for not retryable commands#2048
vbabanin wants to merge 1 commit into
mongodb:backpressurefrom
vbabanin:support-non-retry-command

Conversation

@vbabanin

@vbabanin vbabanin commented Sep 6, 2026

Copy link
Copy Markdown
Member

Summary

Adds overload-only retry support to 11 write-command operations that previously dispatched commands without any retry wrapper.

The retry policy is gated on retryWrites and uses:

includeOverload(maxAdaptiveRetriesSetting, ErrorPropagation.AS_WRITE_POLICY)

It intentionally does not use includeWrite(), because these commands are not retryable writes under the retryable-writes spec.

Commands covered

Command Operation
createIndexes CreateIndexesOperation
dropIndexes DropIndexOperation
create CreateCollectionOperation
create view CreateViewOperation
drop DropCollectionOperation
dropDatabase DropDatabaseOperation
renameCollection RenameCollectionOperation
aggregate with $out / $merge AggregateToCollectionOperation
createSearchIndexes CreateSearchIndexesOperation
updateSearchIndex UpdateSearchIndexesOperation
dropSearchIndex DropSearchIndexOperation

Implementation details

  • Wraps sync dispatch with createSpecRetryControl + decorateWithRetries.
  • Wraps async dispatch with createSpecRetryControl + decorateWithRetriesAsync.
  • Each retry attempt performs a fresh connection selection.
  • Adds onCommand(this::getCommandName) for retry debug logging.
  • Threads retryWrites and maxAdaptiveRetriesSetting from the client layer through Operations into the affected operations.
  • Fixes sync aggregate so $out / $merge respects the actual retryWrites setting instead of always using true. (//TODO check this)

Scope notes

Already covered before this change:

  • updateMany / deleteMany / bulkWrite
  • findAndModify
  • runCommand
  • getMore
  • regular read operations through executeRetryableRead

Intentionally excluded:

Excluded Reason
mapReduce Deprecated / removed; no peer-driver precedent.
{w:0} writes No server response exists to carry an overload error.
killCursors Handled separately.
Monitoring / RTT / auth / connection setup Explicitly excluded by the backpressure spec.

Test coverage

  • Removed JAVA-5956 skips for unified client-backpressure tests:
    • createIndex
    • dropIndex
    • dropIndexes
    • aggregate write retry
  • Added prose tests for:
    • create/drop index
    • create collection/view
    • drop collection/database
    • rename collection
    • create/update/drop search index
  • Search-index tests are gated on server version and Atlas Search helper availability.

…d/write retry policies

- Implements overload-only retry (gated on retryWrites, per client-backpressure) for the write commands that previously dispatched with no retry wrapper: createIndexes, dropIndexes, create/drop/rename collection, aggregate with $out/$merge, and the search-index commands.
- Removes the JAVA-5956 skips that hid these commands from the unified client-backpressure suite, and adds prose tests (not part of the spec suite) covering the commands that have no unified test coverage.

JAVA-6308

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Constructor compatibility, legacy integration, and multi-command retry-scope defects must be resolved.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds retryWrites-gated overload retries to previously non-retryable write commands across core and synchronous driver paths.

Changes:

  • Adds synchronous and asynchronous overload retry loops for DDL and search-index operations.
  • Propagates retry settings to write aggregations.
  • Enables unified backpressure tests and adds prose coverage.

Human review is required. Blocking issues include stale constructor call sites, incomplete legacy-driver wiring, and incorrect retry scopes for encrypted collection operations.

File summaries
File Description
UnifiedTestModifications.java Re-enables backpressure tests.
BackpressureProseTest.java Adds command retry coverage.
MongoDatabaseImpl.java Propagates aggregate retryWrites.
MongoCollectionImpl.java Propagates aggregate retryWrites.
AggregateIterableImpl.java Accepts write retry settings.
UpdateSearchIndexesOperation.java Adds retry configuration.
RenameCollectionOperation.java Adds overload retry loop.
Operations.java Wires retry settings into operations.
DropSearchIndexOperation.java Adds retry configuration.
DropIndexOperation.java Adds overload retry loop.
DropDatabaseOperation.java Adds overload retry loop.
DropCollectionOperation.java Adds overload retry loop.
CreateViewOperation.java Adds overload retry loop.
CreateSearchIndexesOperation.java Adds retry configuration.
CreateIndexesOperation.java Adds overload retry loop.
CreateCollectionOperation.java Adds overload retry loop.
AggregateToCollectionOperation.java Enables write-gated overload retries.
AbstractWriteSearchIndexOperation.java Centralizes search-index retries.
Review details
  • Files reviewed: 18/18 changed files
  • Comments generated: 4
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

final ReadConcern readConcern, final WriteConcern writeConcern, final OperationExecutor executor,
final List<? extends Bson> pipeline, final AggregationLevel aggregationLevel,
final boolean retryReads, @Nullable final Integer maxAdaptiveRetriesSetting,
final boolean retryWrites, final boolean retryReads, @Nullable final Integer maxAdaptiveRetriesSetting,
Comment on lines +271 to +275
Supplier<Void> retryingCommandExecutor = decorateWithRetries(retryControl, operationContext, () -> {
retryControl.getPolicy().onCommand(this::getCommandName);
return withConnection(binding, operationContext, (connection, operationContextWithMinRtt) -> {
checkEncryptedFieldsSupported(connection.getDescription());
getCommandFunctions().forEach(commandCreator ->
Comment on lines +150 to +152
AsyncCallbackSupplier<Void> retryingCommandExecutor = decorateWithRetriesAsync(retryControl, operationContext, supplierCallback -> {
SingleResultCallback<Void> errHandlingCallback = errorHandlingCallback(supplierCallback, LOGGER);
getEncryptedFields((AsyncReadWriteBinding) binding, operationContext, (result, t) -> {
Comment on lines 622 to +623
CreateCollectionOperation operation = new CreateCollectionOperation(
assertNotNull(namespace).getDatabaseName(), collectionName, writeConcern)
assertNotNull(namespace).getDatabaseName(), collectionName, writeConcern, isRetryWrites(), maxAdaptiveRetriesSetting)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants