From af54ac3b56b7ef33c75df928fa0dd09fc48547b9 Mon Sep 17 00:00:00 2001 From: Noah Stapp Date: Tue, 10 Mar 2026 12:38:02 -0400 Subject: [PATCH] Add more tests --- pymongo/asynchronous/collection.py | 1 + pymongo/asynchronous/mongo_client.py | 17 +- pymongo/synchronous/collection.py | 1 + pymongo/synchronous/mongo_client.py | 17 +- .../backpressure-retry-loop.json | 2200 ++++++++++++++++- .../backpressure-retry-max-attempts.json | 175 +- .../backpressure-runCommand-requirements.json | 281 --- 7 files changed, 2335 insertions(+), 357 deletions(-) delete mode 100644 test/client-backpressure/backpressure-runCommand-requirements.json diff --git a/pymongo/asynchronous/collection.py b/pymongo/asynchronous/collection.py index 4de72af47..127136dd4 100644 --- a/pymongo/asynchronous/collection.py +++ b/pymongo/asynchronous/collection.py @@ -2946,6 +2946,7 @@ class AsyncCollection(common.BaseObject, Generic[_DocumentType]): session, retryable=not cmd._performs_write, operation=_Op.AGGREGATE, + is_aggregate_write=cmd._performs_write, ) async def aggregate( diff --git a/pymongo/asynchronous/mongo_client.py b/pymongo/asynchronous/mongo_client.py index 509f2742f..d69f3ca70 100644 --- a/pymongo/asynchronous/mongo_client.py +++ b/pymongo/asynchronous/mongo_client.py @@ -2010,6 +2010,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]): retryable: bool = False, operation_id: Optional[int] = None, is_run_command: bool = False, + is_aggregate_write: bool = False, ) -> T: """Internal retryable helper for all client transactions. @@ -2022,6 +2023,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]): :param read_pref: Topology of read operation, defaults to None :param retryable: If the operation should be retried once, defaults to None :param is_run_command: If this is a runCommand operation, defaults to False + :param is_aggregate_write: If this is a aggregate operation with a write, defaults to False. :return: Output of the calling func() """ @@ -2037,6 +2039,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]): retryable=retryable, operation_id=operation_id, is_run_command=is_run_command, + is_aggregate_write=is_aggregate_write, ).run() async def _retryable_read( @@ -2049,6 +2052,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]): retryable: bool = True, operation_id: Optional[int] = None, is_run_command: bool = False, + is_aggregate_write: bool = False, ) -> T: """Execute an operation with consecutive retries if possible @@ -2065,6 +2069,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]): :param retryable: if we should attempt retries (may not always be supported even if supplied), defaults to False :param is_run_command: If this is a runCommand operation, defaults to False. + :param is_aggregate_write: If this is a aggregate operation with a write, defaults to False. """ # Ensure that the client supports retrying on reads and there is no session in @@ -2084,6 +2089,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]): retryable=retryable, operation_id=operation_id, is_run_command=is_run_command, + is_aggregate_write=is_aggregate_write, ) async def _retryable_write( @@ -2754,6 +2760,7 @@ class _ClientConnectionRetryable(Generic[T]): retryable: bool = False, operation_id: Optional[int] = None, is_run_command: bool = False, + is_aggregate_write: bool = False, ): self._last_error: Optional[Exception] = None self._retrying = False @@ -2777,6 +2784,7 @@ class _ClientConnectionRetryable(Generic[T]): self._operation_id = operation_id self._attempt_number = 0 self._is_run_command = is_run_command + self._is_aggregate_write = is_aggregate_write async def run(self) -> T: """Runs the supplied func() and attempts a retry @@ -2822,6 +2830,9 @@ class _ClientConnectionRetryable(Generic[T]): self._client.options.retry_reads and self._client.options.retry_writes ): raise + if self._is_aggregate_write and not self._client.options.retry_writes: + raise + # Execute specialized catch on read if self._is_read: if isinstance(exc, (ConnectionFailure, OperationFailure)): @@ -2870,9 +2881,9 @@ class _ClientConnectionRetryable(Generic[T]): always_retryable = exc_to_check.has_error_label("RetryableError") and overloaded # Always retry abortTransaction and commitTransaction up to once - if not (self._client.options.retry_writes and self._retryable) and ( - not always_retryable - and self._operation not in ["abortTransaction", "commitTransaction"] + if self._operation not in ["abortTransaction", "commitTransaction"] and ( + not self._client.options.retry_writes + or not (self._retryable or always_retryable) ): raise if retryable_write_label or always_retryable: diff --git a/pymongo/synchronous/collection.py b/pymongo/synchronous/collection.py index 73207d602..34fd7190d 100644 --- a/pymongo/synchronous/collection.py +++ b/pymongo/synchronous/collection.py @@ -2939,6 +2939,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]): session, retryable=not cmd._performs_write, operation=_Op.AGGREGATE, + is_aggregate_write=cmd._performs_write, ) def aggregate( diff --git a/pymongo/synchronous/mongo_client.py b/pymongo/synchronous/mongo_client.py index f1e6024ce..ae11be816 100644 --- a/pymongo/synchronous/mongo_client.py +++ b/pymongo/synchronous/mongo_client.py @@ -2006,6 +2006,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): retryable: bool = False, operation_id: Optional[int] = None, is_run_command: bool = False, + is_aggregate_write: bool = False, ) -> T: """Internal retryable helper for all client transactions. @@ -2018,6 +2019,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): :param read_pref: Topology of read operation, defaults to None :param retryable: If the operation should be retried once, defaults to None :param is_run_command: If this is a runCommand operation, defaults to False + :param is_aggregate_write: If this is a aggregate operation with a write, defaults to False. :return: Output of the calling func() """ @@ -2033,6 +2035,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): retryable=retryable, operation_id=operation_id, is_run_command=is_run_command, + is_aggregate_write=is_aggregate_write, ).run() def _retryable_read( @@ -2045,6 +2048,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): retryable: bool = True, operation_id: Optional[int] = None, is_run_command: bool = False, + is_aggregate_write: bool = False, ) -> T: """Execute an operation with consecutive retries if possible @@ -2061,6 +2065,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): :param retryable: if we should attempt retries (may not always be supported even if supplied), defaults to False :param is_run_command: If this is a runCommand operation, defaults to False. + :param is_aggregate_write: If this is a aggregate operation with a write, defaults to False. """ # Ensure that the client supports retrying on reads and there is no session in @@ -2080,6 +2085,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): retryable=retryable, operation_id=operation_id, is_run_command=is_run_command, + is_aggregate_write=is_aggregate_write, ) def _retryable_write( @@ -2744,6 +2750,7 @@ class _ClientConnectionRetryable(Generic[T]): retryable: bool = False, operation_id: Optional[int] = None, is_run_command: bool = False, + is_aggregate_write: bool = False, ): self._last_error: Optional[Exception] = None self._retrying = False @@ -2767,6 +2774,7 @@ class _ClientConnectionRetryable(Generic[T]): self._operation_id = operation_id self._attempt_number = 0 self._is_run_command = is_run_command + self._is_aggregate_write = is_aggregate_write def run(self) -> T: """Runs the supplied func() and attempts a retry @@ -2812,6 +2820,9 @@ class _ClientConnectionRetryable(Generic[T]): self._client.options.retry_reads and self._client.options.retry_writes ): raise + if self._is_aggregate_write and not self._client.options.retry_writes: + raise + # Execute specialized catch on read if self._is_read: if isinstance(exc, (ConnectionFailure, OperationFailure)): @@ -2860,9 +2871,9 @@ class _ClientConnectionRetryable(Generic[T]): always_retryable = exc_to_check.has_error_label("RetryableError") and overloaded # Always retry abortTransaction and commitTransaction up to once - if not (self._client.options.retry_writes and self._retryable) and ( - not always_retryable - and self._operation not in ["abortTransaction", "commitTransaction"] + if self._operation not in ["abortTransaction", "commitTransaction"] and ( + not self._client.options.retry_writes + or not (self._retryable or always_retryable) ): raise if retryable_write_label or always_retryable: diff --git a/test/client-backpressure/backpressure-retry-loop.json b/test/client-backpressure/backpressure-retry-loop.json index 2542344b3..0e8840f52 100644 --- a/test/client-backpressure/backpressure-retry-loop.json +++ b/test/client-backpressure/backpressure-retry-loop.json @@ -20,6 +20,9 @@ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" ] } }, @@ -56,6 +59,68 @@ "database": "database", "collectionName": "coll" } + }, + { + "client": { + "id": "client_retryReads_false", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent", + "commandFailedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ], + "uriOptions": { + "retryReads": false + } + } + }, + { + "database": { + "id": "database_retryReads_false", + "client": "client_retryReads_false", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection_retryReads_false", + "database": "database_retryReads_false", + "collectionName": "coll" + } + }, + { + "client": { + "id": "client_retryWrites_false", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent", + "commandFailedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ], + "uriOptions": { + "retryWrites": false + } + } + }, + { + "database": { + "id": "database_retryWrites_false", + "client": "client_retryWrites_false", + "databaseName": "backpressure-db" + } + }, + { + "collection": { + "id": "collection_retryWrites_false", + "database": "database_retryWrites_false", + "collectionName": "coll" + } } ], "initialData": [ @@ -96,8 +161,8 @@ } }, { - "object": "client", "name": "listDatabases", + "object": "client", "arguments": { "filter": {} } @@ -151,6 +216,62 @@ } ] }, + { + "description": "client.listDatabases (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "listDatabases", + "object": "client_retryReads_false", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "listDatabases" + } + }, + { + "commandFailedEvent": { + "commandName": "listDatabases" + } + } + ] + } + ] + }, { "description": "client.listDatabaseNames retries using operation loop", "operations": [ @@ -178,8 +299,8 @@ } }, { - "object": "client", - "name": "listDatabaseNames" + "name": "listDatabaseNames", + "object": "client" } ], "expectEvents": [ @@ -230,6 +351,59 @@ } ] }, + { + "description": "client.listDatabaseNames (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "listDatabaseNames", + "object": "client_retryReads_false", + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "listDatabases" + } + }, + { + "commandFailedEvent": { + "commandName": "listDatabases" + } + } + ] + } + ] + }, { "description": "client.createChangeStream retries using operation loop", "operations": [ @@ -257,8 +431,8 @@ } }, { - "object": "client", "name": "createChangeStream", + "object": "client", "arguments": { "pipeline": [] } @@ -312,6 +486,62 @@ } ] }, + { + "description": "client.createChangeStream (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "createChangeStream", + "object": "client_retryReads_false", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + } + ] + } + ] + }, { "description": "client.clientBulkWrite retries using operation loop", "runOnRequirements": [ @@ -344,8 +574,8 @@ } }, { - "object": "client", "name": "clientBulkWrite", + "object": "client", "arguments": { "models": [ { @@ -409,6 +639,77 @@ } ] }, + { + "description": "client.clientBulkWrite (write) does not retry if retryWrites=false", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "clientBulkWrite", + "object": "client_retryWrites_false", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite" + } + }, + { + "commandFailedEvent": { + "commandName": "bulkWrite" + } + } + ] + } + ] + }, { "description": "database.aggregate retries using operation loop", "operations": [ @@ -436,8 +737,8 @@ } }, { - "object": "database", "name": "aggregate", + "object": "database", "arguments": { "pipeline": [ { @@ -498,6 +799,69 @@ } ] }, + { + "description": "database.aggregate (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "aggregate", + "object": "database_retryReads_false", + "arguments": { + "pipeline": [ + { + "$listLocalSessions": {} + }, + { + "$limit": 1 + } + ] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + } + ] + } + ] + }, { "description": "database.listCollections retries using operation loop", "operations": [ @@ -525,8 +889,8 @@ } }, { - "object": "database", "name": "listCollections", + "object": "database", "arguments": { "filter": {} } @@ -580,6 +944,62 @@ } ] }, + { + "description": "database.listCollections (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "listCollections", + "object": "database_retryReads_false", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "listCollections" + } + }, + { + "commandFailedEvent": { + "commandName": "listCollections" + } + } + ] + } + ] + }, { "description": "database.listCollectionNames retries using operation loop", "operations": [ @@ -607,8 +1027,8 @@ } }, { - "object": "database", "name": "listCollectionNames", + "object": "database", "arguments": { "filter": {} } @@ -662,6 +1082,62 @@ } ] }, + { + "description": "database.listCollectionNames (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "listCollectionNames", + "object": "database_retryReads_false", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "listCollections" + } + }, + { + "commandFailedEvent": { + "commandName": "listCollections" + } + } + ] + } + ] + }, { "description": "database.runCommand retries using operation loop", "operations": [ @@ -689,8 +1165,8 @@ } }, { - "object": "database", "name": "runCommand", + "object": "database", "arguments": { "command": { "ping": 1 @@ -747,6 +1223,124 @@ } ] }, + { + "description": "database.runCommand (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "ping" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "runCommand", + "object": "database_retryReads_false", + "arguments": { + "command": { + "ping": 1 + }, + "commandName": "ping" + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "ping" + } + }, + { + "commandFailedEvent": { + "commandName": "ping" + } + } + ] + } + ] + }, + { + "description": "database.runCommand (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "ping" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "runCommand", + "object": "database_retryWrites_false", + "arguments": { + "command": { + "ping": 1 + }, + "commandName": "ping" + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "ping" + } + }, + { + "commandFailedEvent": { + "commandName": "ping" + } + } + ] + } + ] + }, { "description": "database.createChangeStream retries using operation loop", "operations": [ @@ -774,8 +1368,8 @@ } }, { - "object": "database", "name": "createChangeStream", + "object": "database", "arguments": { "pipeline": [] } @@ -829,6 +1423,62 @@ } ] }, + { + "description": "database.createChangeStream (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "createChangeStream", + "object": "database_retryReads_false", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + } + ] + } + ] + }, { "description": "collection.aggregate retries using operation loop", "operations": [ @@ -856,8 +1506,8 @@ } }, { - "object": "collection", "name": "aggregate", + "object": "collection", "arguments": { "pipeline": [] } @@ -911,6 +1561,62 @@ } ] }, + { + "description": "collection.aggregate (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "aggregate", + "object": "collection_retryReads_false", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + } + ] + } + ] + }, { "description": "collection.countDocuments retries using operation loop", "operations": [ @@ -938,8 +1644,8 @@ } }, { - "object": "collection", "name": "countDocuments", + "object": "collection", "arguments": { "filter": {} } @@ -993,6 +1699,62 @@ } ] }, + { + "description": "collection.countDocuments (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "countDocuments", + "object": "collection_retryReads_false", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + } + ] + } + ] + }, { "description": "collection.estimatedDocumentCount retries using operation loop", "operations": [ @@ -1020,8 +1782,8 @@ } }, { - "object": "collection", - "name": "estimatedDocumentCount" + "name": "estimatedDocumentCount", + "object": "collection" } ], "expectEvents": [ @@ -1072,6 +1834,59 @@ } ] }, + { + "description": "collection.estimatedDocumentCount (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "estimatedDocumentCount", + "object": "collection_retryReads_false", + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "count" + } + }, + { + "commandFailedEvent": { + "commandName": "count" + } + } + ] + } + ] + }, { "description": "collection.distinct retries using operation loop", "operations": [ @@ -1099,8 +1914,8 @@ } }, { - "object": "collection", "name": "distinct", + "object": "collection", "arguments": { "fieldName": "x", "filter": {} @@ -1155,6 +1970,63 @@ } ] }, + { + "description": "collection.distinct (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "distinct", + "object": "collection_retryReads_false", + "arguments": { + "fieldName": "x", + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "distinct" + } + }, + { + "commandFailedEvent": { + "commandName": "distinct" + } + } + ] + } + ] + }, { "description": "collection.find retries using operation loop", "operations": [ @@ -1182,8 +2054,8 @@ } }, { - "object": "collection", "name": "find", + "object": "collection", "arguments": { "filter": {} } @@ -1237,6 +2109,62 @@ } ] }, + { + "description": "collection.find (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "find", + "object": "collection_retryReads_false", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "find" + } + }, + { + "commandFailedEvent": { + "commandName": "find" + } + } + ] + } + ] + }, { "description": "collection.findOne retries using operation loop", "operations": [ @@ -1264,8 +2192,8 @@ } }, { - "object": "collection", "name": "findOne", + "object": "collection", "arguments": { "filter": {} } @@ -1319,6 +2247,62 @@ } ] }, + { + "description": "collection.findOne (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "findOne", + "object": "collection_retryReads_false", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "find" + } + }, + { + "commandFailedEvent": { + "commandName": "find" + } + } + ] + } + ] + }, { "description": "collection.listIndexes retries using operation loop", "operations": [ @@ -1346,8 +2330,8 @@ } }, { - "object": "collection", - "name": "listIndexes" + "name": "listIndexes", + "object": "collection" } ], "expectEvents": [ @@ -1398,6 +2382,59 @@ } ] }, + { + "description": "collection.listIndexes (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "listIndexes", + "object": "collection_retryReads_false", + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "listIndexes" + } + }, + { + "commandFailedEvent": { + "commandName": "listIndexes" + } + } + ] + } + ] + }, { "description": "collection.listIndexNames retries using operation loop", "operations": [ @@ -1425,8 +2462,8 @@ } }, { - "object": "collection", - "name": "listIndexNames" + "name": "listIndexNames", + "object": "collection" } ], "expectEvents": [ @@ -1477,6 +2514,59 @@ } ] }, + { + "description": "collection.listIndexNames (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "listIndexNames", + "object": "collection_retryReads_false", + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "listIndexes" + } + }, + { + "commandFailedEvent": { + "commandName": "listIndexes" + } + } + ] + } + ] + }, { "description": "collection.createChangeStream retries using operation loop", "operations": [ @@ -1504,8 +2594,8 @@ } }, { - "object": "collection", "name": "createChangeStream", + "object": "collection", "arguments": { "pipeline": [] } @@ -1559,6 +2649,62 @@ } ] }, + { + "description": "collection.createChangeStream (read) does not retry if retryReads=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection_retryReads_false", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryReads_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + } + ] + } + ] + }, { "description": "collection.insertOne retries using operation loop", "operations": [ @@ -1586,8 +2732,8 @@ } }, { - "object": "collection", "name": "insertOne", + "object": "collection", "arguments": { "document": { "_id": 2, @@ -1644,6 +2790,65 @@ } ] }, + { + "description": "collection.insertOne (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "insertOne", + "object": "collection_retryWrites_false", + "arguments": { + "document": { + "_id": 2, + "x": 22 + } + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "insert" + } + }, + { + "commandFailedEvent": { + "commandName": "insert" + } + } + ] + } + ] + }, { "description": "collection.insertMany retries using operation loop", "operations": [ @@ -1671,8 +2876,8 @@ } }, { - "object": "collection", "name": "insertMany", + "object": "collection", "arguments": { "documents": [ { @@ -1731,6 +2936,67 @@ } ] }, + { + "description": "collection.insertMany (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "insertMany", + "object": "collection_retryWrites_false", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "insert" + } + }, + { + "commandFailedEvent": { + "commandName": "insert" + } + } + ] + } + ] + }, { "description": "collection.deleteOne retries using operation loop", "operations": [ @@ -1758,8 +3024,8 @@ } }, { - "object": "collection", "name": "deleteOne", + "object": "collection", "arguments": { "filter": {} } @@ -1813,6 +3079,62 @@ } ] }, + { + "description": "collection.deleteOne (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "delete" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "deleteOne", + "object": "collection_retryWrites_false", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "delete" + } + }, + { + "commandFailedEvent": { + "commandName": "delete" + } + } + ] + } + ] + }, { "description": "collection.deleteMany retries using operation loop", "operations": [ @@ -1840,8 +3162,8 @@ } }, { - "object": "collection", "name": "deleteMany", + "object": "collection", "arguments": { "filter": {} } @@ -1895,6 +3217,62 @@ } ] }, + { + "description": "collection.deleteMany (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "delete" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "deleteMany", + "object": "collection_retryWrites_false", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "delete" + } + }, + { + "commandFailedEvent": { + "commandName": "delete" + } + } + ] + } + ] + }, { "description": "collection.replaceOne retries using operation loop", "operations": [ @@ -1922,8 +3300,8 @@ } }, { - "object": "collection", "name": "replaceOne", + "object": "collection", "arguments": { "filter": {}, "replacement": { @@ -1980,6 +3358,65 @@ } ] }, + { + "description": "collection.replaceOne (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "replaceOne", + "object": "collection_retryWrites_false", + "arguments": { + "filter": {}, + "replacement": { + "x": 22 + } + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "update" + } + }, + { + "commandFailedEvent": { + "commandName": "update" + } + } + ] + } + ] + }, { "description": "collection.updateOne retries using operation loop", "operations": [ @@ -2007,8 +3444,8 @@ } }, { - "object": "collection", "name": "updateOne", + "object": "collection", "arguments": { "filter": {}, "update": { @@ -2067,6 +3504,67 @@ } ] }, + { + "description": "collection.updateOne (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "updateOne", + "object": "collection_retryWrites_false", + "arguments": { + "filter": {}, + "update": { + "$set": { + "x": 22 + } + } + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "update" + } + }, + { + "commandFailedEvent": { + "commandName": "update" + } + } + ] + } + ] + }, { "description": "collection.updateMany retries using operation loop", "operations": [ @@ -2094,8 +3592,8 @@ } }, { - "object": "collection", "name": "updateMany", + "object": "collection", "arguments": { "filter": {}, "update": { @@ -2154,6 +3652,67 @@ } ] }, + { + "description": "collection.updateMany (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "updateMany", + "object": "collection_retryWrites_false", + "arguments": { + "filter": {}, + "update": { + "$set": { + "x": 22 + } + } + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "update" + } + }, + { + "commandFailedEvent": { + "commandName": "update" + } + } + ] + } + ] + }, { "description": "collection.findOneAndDelete retries using operation loop", "operations": [ @@ -2181,8 +3740,8 @@ } }, { - "object": "collection", "name": "findOneAndDelete", + "object": "collection", "arguments": { "filter": {} } @@ -2236,6 +3795,62 @@ } ] }, + { + "description": "collection.findOneAndDelete (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "findOneAndDelete", + "object": "collection_retryWrites_false", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "findAndModify" + } + }, + { + "commandFailedEvent": { + "commandName": "findAndModify" + } + } + ] + } + ] + }, { "description": "collection.findOneAndReplace retries using operation loop", "operations": [ @@ -2263,8 +3878,8 @@ } }, { - "object": "collection", "name": "findOneAndReplace", + "object": "collection", "arguments": { "filter": {}, "replacement": { @@ -2321,6 +3936,65 @@ } ] }, + { + "description": "collection.findOneAndReplace (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "findOneAndReplace", + "object": "collection_retryWrites_false", + "arguments": { + "filter": {}, + "replacement": { + "x": 22 + } + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "findAndModify" + } + }, + { + "commandFailedEvent": { + "commandName": "findAndModify" + } + } + ] + } + ] + }, { "description": "collection.findOneAndUpdate retries using operation loop", "operations": [ @@ -2348,8 +4022,8 @@ } }, { - "object": "collection", "name": "findOneAndUpdate", + "object": "collection", "arguments": { "filter": {}, "update": { @@ -2408,6 +4082,67 @@ } ] }, + { + "description": "collection.findOneAndUpdate (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "findOneAndUpdate", + "object": "collection_retryWrites_false", + "arguments": { + "filter": {}, + "update": { + "$set": { + "x": 22 + } + } + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "findAndModify" + } + }, + { + "commandFailedEvent": { + "commandName": "findAndModify" + } + } + ] + } + ] + }, { "description": "collection.bulkWrite retries using operation loop", "operations": [ @@ -2435,8 +4170,8 @@ } }, { - "object": "collection", "name": "bulkWrite", + "object": "collection", "arguments": { "requests": [ { @@ -2499,6 +4234,71 @@ } ] }, + { + "description": "collection.bulkWrite (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "bulkWrite", + "object": "collection_retryWrites_false", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + } + ] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "insert" + } + }, + { + "commandFailedEvent": { + "commandName": "insert" + } + } + ] + } + ] + }, { "description": "collection.createIndex retries using operation loop", "operations": [ @@ -2526,8 +4326,8 @@ } }, { - "object": "collection", "name": "createIndex", + "object": "collection", "arguments": { "keys": { "x": 11 @@ -2584,12 +4384,71 @@ } ] }, + { + "description": "collection.createIndex (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "createIndexes" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "createIndex", + "object": "collection_retryWrites_false", + "arguments": { + "keys": { + "x": 11 + }, + "name": "x_11" + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "createIndexes" + } + }, + { + "commandFailedEvent": { + "commandName": "createIndexes" + } + } + ] + } + ] + }, { "description": "collection.dropIndex retries using operation loop", "operations": [ { - "object": "retryable-writes-tests", "name": "createIndex", + "object": "retryable-writes-tests", "arguments": { "keys": { "x": 11 @@ -2621,8 +4480,8 @@ } }, { - "object": "collection", "name": "dropIndex", + "object": "collection", "arguments": { "name": "x_11" } @@ -2676,6 +4535,72 @@ } ] }, + { + "description": "collection.dropIndex (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "createIndex", + "object": "retryable-writes-tests", + "arguments": { + "keys": { + "x": 11 + }, + "name": "x_11" + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "dropIndexes" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "dropIndex", + "object": "collection_retryWrites_false", + "arguments": { + "name": "x_11" + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "dropIndexes" + } + }, + { + "commandFailedEvent": { + "commandName": "dropIndexes" + } + } + ] + } + ] + }, { "description": "collection.dropIndexes retries using operation loop", "operations": [ @@ -2703,8 +4628,8 @@ } }, { - "object": "collection", - "name": "dropIndexes" + "name": "dropIndexes", + "object": "collection" } ], "expectEvents": [ @@ -2754,6 +4679,205 @@ ] } ] + }, + { + "description": "collection.dropIndexes (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "dropIndexes" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "dropIndexes", + "object": "collection_retryWrites_false", + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "dropIndexes" + } + }, + { + "commandFailedEvent": { + "commandName": "dropIndexes" + } + } + ] + } + ] + }, + { + "description": "collection.aggregate retries using operation loop", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 3 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "aggregate", + "object": "collection", + "arguments": { + "pipeline": [ + { + "$out": "output" + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + }, + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + }, + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + }, + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandSucceededEvent": { + "commandName": "aggregate" + } + } + ] + } + ] + }, + { + "description": "collection.aggregate (write) does not retry if retryWrites=false", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "internal_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "aggregate", + "object": "collection_retryWrites_false", + "arguments": { + "pipeline": [ + { + "$out": "output" + } + ] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client_retryWrites_false", + "events": [ + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + } + ] + } + ] } ] } diff --git a/test/client-backpressure/backpressure-retry-max-attempts.json b/test/client-backpressure/backpressure-retry-max-attempts.json index 1de8cb38d..1e6f46f07 100644 --- a/test/client-backpressure/backpressure-retry-max-attempts.json +++ b/test/client-backpressure/backpressure-retry-max-attempts.json @@ -20,6 +20,9 @@ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" ] } }, @@ -89,8 +92,8 @@ } }, { - "object": "client", "name": "listDatabases", + "object": "client", "arguments": { "filter": {} }, @@ -193,8 +196,8 @@ } }, { - "object": "client", "name": "listDatabaseNames", + "object": "client", "expectError": { "isError": true, "isClientError": false @@ -294,8 +297,8 @@ } }, { - "object": "client", "name": "createChangeStream", + "object": "client", "arguments": { "pipeline": [] }, @@ -403,8 +406,8 @@ } }, { - "object": "client", "name": "clientBulkWrite", + "object": "client", "arguments": { "models": [ { @@ -517,8 +520,8 @@ } }, { - "object": "database", "name": "aggregate", + "object": "database", "arguments": { "pipeline": [ { @@ -628,8 +631,8 @@ } }, { - "object": "database", "name": "listCollections", + "object": "database", "arguments": { "filter": {} }, @@ -732,8 +735,8 @@ } }, { - "object": "database", "name": "listCollectionNames", + "object": "database", "arguments": { "filter": {} }, @@ -836,8 +839,8 @@ } }, { - "object": "database", "name": "runCommand", + "object": "database", "arguments": { "command": { "ping": 1 @@ -943,8 +946,8 @@ } }, { - "object": "database", "name": "createChangeStream", + "object": "database", "arguments": { "pipeline": [] }, @@ -1047,8 +1050,8 @@ } }, { - "object": "collection", "name": "aggregate", + "object": "collection", "arguments": { "pipeline": [] }, @@ -1151,8 +1154,8 @@ } }, { - "object": "collection", "name": "countDocuments", + "object": "collection", "arguments": { "filter": {} }, @@ -1255,8 +1258,8 @@ } }, { - "object": "collection", "name": "estimatedDocumentCount", + "object": "collection", "expectError": { "isError": true, "isClientError": false @@ -1356,8 +1359,8 @@ } }, { - "object": "collection", "name": "distinct", + "object": "collection", "arguments": { "fieldName": "x", "filter": {} @@ -1461,8 +1464,8 @@ } }, { - "object": "collection", "name": "find", + "object": "collection", "arguments": { "filter": {} }, @@ -1565,8 +1568,8 @@ } }, { - "object": "collection", "name": "findOne", + "object": "collection", "arguments": { "filter": {} }, @@ -1669,8 +1672,8 @@ } }, { - "object": "collection", "name": "listIndexes", + "object": "collection", "expectError": { "isError": true, "isClientError": false @@ -1770,8 +1773,8 @@ } }, { - "object": "collection", "name": "listIndexNames", + "object": "collection", "expectError": { "isError": true, "isClientError": false @@ -1871,8 +1874,8 @@ } }, { - "object": "collection", "name": "createChangeStream", + "object": "collection", "arguments": { "pipeline": [] }, @@ -1975,8 +1978,8 @@ } }, { - "object": "collection", "name": "insertOne", + "object": "collection", "arguments": { "document": { "_id": 2, @@ -2082,8 +2085,8 @@ } }, { - "object": "collection", "name": "insertMany", + "object": "collection", "arguments": { "documents": [ { @@ -2191,8 +2194,8 @@ } }, { - "object": "collection", "name": "deleteOne", + "object": "collection", "arguments": { "filter": {} }, @@ -2295,8 +2298,8 @@ } }, { - "object": "collection", "name": "deleteMany", + "object": "collection", "arguments": { "filter": {} }, @@ -2399,8 +2402,8 @@ } }, { - "object": "collection", "name": "replaceOne", + "object": "collection", "arguments": { "filter": {}, "replacement": { @@ -2506,8 +2509,8 @@ } }, { - "object": "collection", "name": "updateOne", + "object": "collection", "arguments": { "filter": {}, "update": { @@ -2615,8 +2618,8 @@ } }, { - "object": "collection", "name": "updateMany", + "object": "collection", "arguments": { "filter": {}, "update": { @@ -2724,8 +2727,8 @@ } }, { - "object": "collection", "name": "findOneAndDelete", + "object": "collection", "arguments": { "filter": {} }, @@ -2828,8 +2831,8 @@ } }, { - "object": "collection", "name": "findOneAndReplace", + "object": "collection", "arguments": { "filter": {}, "replacement": { @@ -2935,8 +2938,8 @@ } }, { - "object": "collection", "name": "findOneAndUpdate", + "object": "collection", "arguments": { "filter": {}, "update": { @@ -3044,8 +3047,8 @@ } }, { - "object": "collection", "name": "bulkWrite", + "object": "collection", "arguments": { "requests": [ { @@ -3157,8 +3160,8 @@ } }, { - "object": "collection", "name": "createIndex", + "object": "collection", "arguments": { "keys": { "x": 11 @@ -3264,8 +3267,8 @@ } }, { - "object": "collection", "name": "dropIndex", + "object": "collection", "arguments": { "name": "x_11" }, @@ -3368,8 +3371,8 @@ } }, { - "object": "collection", "name": "dropIndexes", + "object": "collection", "expectError": { "isError": true, "isClientError": false @@ -3443,6 +3446,114 @@ ] } ] + }, + { + "description": "collection.aggregate retries at most maxAttempts=5 times", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "fail_point_client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": "alwaysOn", + "data": { + "failCommands": [ + "aggregate" + ], + "errorLabels": [ + "RetryableError", + "SystemOverloadedError" + ], + "errorCode": 2 + } + } + } + }, + { + "name": "aggregate", + "object": "collection", + "arguments": { + "pipeline": [ + { + "$out": "output" + } + ] + }, + "expectError": { + "isError": true, + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + }, + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + }, + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + }, + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + }, + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + }, + { + "commandStartedEvent": { + "commandName": "aggregate" + } + }, + { + "commandFailedEvent": { + "commandName": "aggregate" + } + } + ] + } + ] } ] } diff --git a/test/client-backpressure/backpressure-runCommand-requirements.json b/test/client-backpressure/backpressure-runCommand-requirements.json deleted file mode 100644 index 4cfb04e19..000000000 --- a/test/client-backpressure/backpressure-runCommand-requirements.json +++ /dev/null @@ -1,281 +0,0 @@ -{ - "description": "tests that runCommand only retries when retryReads=true and retryWrites=true", - "schemaVersion": "1.3", - "runOnRequirements": [ - { - "minServerVersion": "4.4", - "topologies": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "createEntities": [ - { - "client": { - "id": "client_defaults", - "useMultipleMongoses": false, - "observeEvents": [ - "commandStartedEvent", - "commandSucceededEvent", - "commandFailedEvent" - ] - } - }, - { - "database": { - "id": "database_defaults", - "client": "client_defaults", - "databaseName": "backpressure-runCommand-requirements-db" - } - }, - { - "client": { - "id": "client_retryReads_false", - "useMultipleMongoses": false, - "observeEvents": [ - "commandStartedEvent", - "commandSucceededEvent", - "commandFailedEvent" - ], - "uriOptions": { - "retryReads": false - } - } - }, - { - "database": { - "id": "database_retryReads_false", - "client": "client_retryReads_false", - "databaseName": "backpressure-runCommand-requirements-db" - } - }, - { - "collection": { - "id": "retryable-reads-tests", - "database": "database_retryReads_false", - "collectionName": "coll_retryReads_false" - } - }, - { - "client": { - "id": "client_retryWrites_false", - "useMultipleMongoses": false, - "observeEvents": [ - "commandStartedEvent", - "commandSucceededEvent", - "commandFailedEvent" - ], - "uriOptions": { - "retryWrites": false - } - } - }, - { - "database": { - "id": "database_retryWrites_false", - "client": "client_retryWrites_false", - "databaseName": "backpressure-runCommand-requirements-db" - } - }, - { - "collection": { - "id": "retryable-writes-tests", - "database": "database_retryWrites_false", - "collectionName": "coll_retryWrites_false" - } - }, - { - "client": { - "id": "internal_client", - "useMultipleMongoses": false - } - } - ], - "tests": [ - { - "description": "database.runCommand retries with defaults (retryReads=true and retryWrites=true)", - "operations": [ - { - "name": "failPoint", - "object": "testRunner", - "arguments": { - "client": "internal_client", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "ping" - ], - "errorLabels": [ - "RetryableError", - "SystemOverloadedError" - ], - "errorCode": 2 - } - } - } - }, - { - "name": "runCommand", - "object": "database_defaults", - "arguments": { - "command": { - "ping": 1 - }, - "commandName": "ping" - } - } - ], - "expectEvents": [ - { - "client": "client_defaults", - "events": [ - { - "commandStartedEvent": { - "commandName": "ping" - } - }, - { - "commandFailedEvent": { - "commandName": "ping" - } - }, - { - "commandStartedEvent": { - "commandName": "ping" - } - }, - { - "commandSucceededEvent": { - "commandName": "ping" - } - } - ] - } - ] - }, - { - "description": "database.runCommand does not retry when retryReads=false", - "operations": [ - { - "name": "failPoint", - "object": "testRunner", - "arguments": { - "client": "internal_client", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "ping" - ], - "errorLabels": [ - "RetryableError", - "SystemOverloadedError" - ], - "errorCode": 2 - } - } - } - }, - { - "name": "runCommand", - "object": "database_retryReads_false", - "arguments": { - "command": { - "ping": 1 - }, - "commandName": "ping" - }, - "expectError": { - "isError": true, - "isClientError": false - } - } - ], - "expectEvents": [ - { - "client": "client_retryReads_false", - "events": [ - { - "commandStartedEvent": { - "commandName": "ping" - } - }, - { - "commandFailedEvent": { - "commandName": "ping" - } - } - ] - } - ] - }, - { - "description": "database.runCommand does not retry when retryWrites=false", - "operations": [ - { - "name": "failPoint", - "object": "testRunner", - "arguments": { - "client": "internal_client", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "ping" - ], - "errorLabels": [ - "RetryableError", - "SystemOverloadedError" - ], - "errorCode": 2 - } - } - } - }, - { - "name": "runCommand", - "object": "database_retryWrites_false", - "arguments": { - "command": { - "ping": 1 - }, - "commandName": "ping" - }, - "expectError": { - "isError": true, - "isClientError": false - } - } - ], - "expectEvents": [ - { - "client": "client_retryWrites_false", - "events": [ - { - "commandStartedEvent": { - "commandName": "ping" - } - }, - { - "commandFailedEvent": { - "commandName": "ping" - } - } - ] - } - ] - } - ] -}