diff options
author | Ben Caimano <ben.caimano@mongodb.com> | 2019-09-09 18:45:01 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-09-09 18:45:01 +0000 |
commit | 0f16c5fc452d16c5a92e43e9fdd96f3822f05271 (patch) | |
tree | 890ff8a80ae78d7831452aedb30feb9e76be1567 /src/mongo | |
parent | f4e387fa1b7e369ce067650bdda9c8676683b929 (diff) | |
download | mongo-0f16c5fc452d16c5a92e43e9fdd96f3822f05271.tar.gz |
SERVER-42908 Add ErrorCodes to retryable errors to match drivers
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/base/error_codes.yml | 625 | ||||
-rw-r--r-- | src/mongo/client/fetcher_test.cpp | 10 | ||||
-rw-r--r-- | src/mongo/client/remote_command_retry_scheduler.cpp | 89 | ||||
-rw-r--r-- | src/mongo/client/remote_command_retry_scheduler.h | 90 | ||||
-rw-r--r-- | src/mongo/client/remote_command_retry_scheduler_test.cpp | 49 | ||||
-rw-r--r-- | src/mongo/db/repl/collection_cloner.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/repl/database_cloner.cpp | 32 | ||||
-rw-r--r-- | src/mongo/db/repl/databases_cloner.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/repl/initial_syncer.cpp | 36 | ||||
-rw-r--r-- | src/mongo/s/client/shard.cpp | 6 | ||||
-rw-r--r-- | src/mongo/s/client/shard_remote.cpp | 19 | ||||
-rw-r--r-- | src/mongo/s/query/establish_cursors.cpp | 8 | ||||
-rw-r--r-- | src/mongo/s/transaction_router.cpp | 11 | ||||
-rw-r--r-- | src/mongo/util/assert_util_test.cpp | 14 |
14 files changed, 478 insertions, 526 deletions
diff --git a/src/mongo/base/error_codes.yml b/src/mongo/base/error_codes.yml index 154eda988c0..fec5207822c 100644 --- a/src/mongo/base/error_codes.yml +++ b/src/mongo/base/error_codes.yml @@ -1,17 +1,17 @@ -# Group related errors into categories, can be checked against ErrorCodes::isXXXClassName methods. +# Group related errors into categories,can be checked against ErrorCodes::isXXXClassName methods. error_categories: - NetworkError - Interruption # isNotMasterError() includes all codes that indicate that the node that received the request - # was not master at some point during command processing, regardless of whether some write may - # have happened. If you care about whether a write could have happened, check for individual + # was not master at some point during command processing,regardless of whether some write may + # have happened. If you care about whether a write could have happened,check for individual # codes. - NotMasterError - StaleShardVersionError - NeedRetargettingError - WriteConcernError - ShutdownError - # isCancelationError() includes all codes that, when passed to a function as its parameter + # isCancelationError() includes all codes that,when passed to a function as its parameter # indicates that it cannot be executed as normal and must abort its intended work. - CancelationError - ConnectionFatalMessageParseError @@ -19,333 +19,334 @@ error_categories: - SnapshotError - VoteAbortError - NonResumableChangeStreamError + - RetriableError error_codes: - - {code: 0, name: OK} - - {code: 1, name: InternalError} - - {code: 2, name: BadValue} - - {code: 3, name: OBSOLETE_DuplicateKey} - - {code: 4, name: NoSuchKey} - - {code: 5, name: GraphContainsCycle} - - {code: 6, name: HostUnreachable, categories: [NetworkError]} - - {code: 7, name: HostNotFound, categories: [NetworkError]} - - {code: 8, name: UnknownError} - - {code: 9, name: FailedToParse} - - {code: 10, name: CannotMutateObject} - - {code: 11, name: UserNotFound} - - {code: 12, name: UnsupportedFormat} - - {code: 13, name: Unauthorized} - - {code: 14, name: TypeMismatch} - - {code: 15, name: Overflow} - - {code: 16, name: InvalidLength} - - {code: 17, name: ProtocolError} - - {code: 18, name: AuthenticationFailed} - - {code: 19, name: CannotReuseObject} - - {code: 20, name: IllegalOperation} - - {code: 21, name: EmptyArrayOperation} - - {code: 22, name: InvalidBSON} - - {code: 23, name: AlreadyInitialized} - - {code: 24, name: LockTimeout, categories: [Interruption]} - - {code: 25, name: RemoteValidationError} - - {code: 26, name: NamespaceNotFound} - - {code: 27, name: IndexNotFound} - - {code: 28, name: PathNotViable} - - {code: 29, name: NonExistentPath} - - {code: 30, name: InvalidPath} - - {code: 31, name: RoleNotFound} - - {code: 32, name: RolesNotRelated} - - {code: 33, name: PrivilegeNotFound} - - {code: 34, name: CannotBackfillArray} - - {code: 35, name: UserModificationFailed} - - {code: 36, name: RemoteChangeDetected} - - {code: 37, name: FileRenameFailed} - - {code: 38, name: FileNotOpen} - - {code: 39, name: FileStreamFailed} - - {code: 40, name: ConflictingUpdateOperators} - - {code: 41, name: FileAlreadyOpen} - - {code: 42, name: LogWriteFailed} - - {code: 43, name: CursorNotFound} - - {code: 45, name: UserDataInconsistent} - - {code: 46, name: LockBusy} - - {code: 47, name: NoMatchingDocument} - - {code: 48, name: NamespaceExists} - - {code: 49, name: InvalidRoleModification} - - {code: 50, name: MaxTimeMSExpired, categories: [Interruption,ExceededTimeLimitError]} - - {code: 51, name: ManualInterventionRequired} - - {code: 52, name: DollarPrefixedFieldName} - - {code: 53, name: InvalidIdField} - - {code: 54, name: NotSingleValueField} - - {code: 55, name: InvalidDBRef} - - {code: 56, name: EmptyFieldName} - - {code: 57, name: DottedFieldName} - - {code: 58, name: RoleModificationFailed} - - {code: 59, name: CommandNotFound} - - {code: 60, name: OBSOLETE_DatabaseNotFound} - - {code: 61, name: ShardKeyNotFound} - - {code: 62, name: OplogOperationUnsupported} - - {code: 63, name: StaleShardVersion, categories: [StaleShardVersionError,NeedRetargettingError]} - - {code: 64, name: WriteConcernFailed, categories: [WriteConcernError]} - - {code: 65, name: MultipleErrorsOccurred} - - {code: 66, name: ImmutableField} - - {code: 67, name: CannotCreateIndex} - - {code: 68, name: IndexAlreadyExists} - - {code: 69, name: AuthSchemaIncompatible} - - {code: 70, name: ShardNotFound} - - {code: 71, name: ReplicaSetNotFound} - - {code: 72, name: InvalidOptions} - - {code: 73, name: InvalidNamespace} - - {code: 74, name: NodeNotFound} - - {code: 75, name: WriteConcernLegacyOK, categories: [WriteConcernError]} - - {code: 76, name: NoReplicationEnabled} - - {code: 77, name: OperationIncomplete} - - {code: 78, name: CommandResultSchemaViolation} - - {code: 79, name: UnknownReplWriteConcern, categories: [WriteConcernError]} - - {code: 80, name: RoleDataInconsistent} - - {code: 81, name: NoMatchParseContext} - - {code: 82, name: NoProgressMade} - - {code: 83, name: RemoteResultsUnavailable} - - {code: 84, name: DuplicateKeyValue} - - {code: 85, name: IndexOptionsConflict} - - {code: 86, name: IndexKeySpecsConflict} - - {code: 87, name: CannotSplit} - - {code: 88, name: SplitFailed_OBSOLETE} - - {code: 89, name: NetworkTimeout, categories: [NetworkError]} - - {code: 90, name: CallbackCanceled, categories: [CancelationError]} - - {code: 91, name: ShutdownInProgress, categories: [ShutdownError, CancelationError]} - - {code: 92, name: SecondaryAheadOfPrimary} - - {code: 93, name: InvalidReplicaSetConfig} - - {code: 94, name: NotYetInitialized} - - {code: 95, name: NotSecondary} - - {code: 96, name: OperationFailed} - - {code: 97, name: NoProjectionFound} - - {code: 98, name: DBPathInUse} - - {code: 100, name: UnsatisfiableWriteConcern, categories: [WriteConcernError]} - - {code: 101, name: OutdatedClient} - - {code: 102, name: IncompatibleAuditMetadata} - - {code: 103, name: NewReplicaSetConfigurationIncompatible} - - {code: 104, name: NodeNotElectable} - - {code: 105, name: IncompatibleShardingMetadata} - - {code: 106, name: DistributedClockSkewed} - - {code: 107, name: LockFailed} - - {code: 108, name: InconsistentReplicaSetNames} - - {code: 109, name: ConfigurationInProgress} - - {code: 110, name: CannotInitializeNodeWithData} - - {code: 111, name: NotExactValueField} - - {code: 112, name: WriteConflict} - - {code: 113, name: InitialSyncFailure} - - {code: 114, name: InitialSyncOplogSourceMissing} - - {code: 115, name: CommandNotSupported} - - {code: 116, name: DocTooLargeForCapped} - - {code: 117, name: ConflictingOperationInProgress} - - {code: 118, name: NamespaceNotSharded} - - {code: 119, name: InvalidSyncSource} - - {code: 120, name: OplogStartMissing} - - {code: 121, name: DocumentValidationFailure} # Only for the document validator on collections. - - {code: 122, name: OBSOLETE_ReadAfterOptimeTimeout} - - {code: 123, name: NotAReplicaSet} - - {code: 124, name: IncompatibleElectionProtocol} - - {code: 125, name: CommandFailed} - - {code: 126, name: RPCProtocolNegotiationFailed} - - {code: 127, name: UnrecoverableRollbackError} - - {code: 128, name: LockNotFound} - - {code: 129, name: LockStateChangeFailed} - - {code: 130, name: SymbolNotFound} - #- {code: 131, name: RLPInitializationFailed} # Removed in 4.2 - - {code: 132, name: OBSOLETE_ConfigServersInconsistent} - - {code: 133, name: FailedToSatisfyReadPreference} - - {code: 134, name: ReadConcernMajorityNotAvailableYet} - - {code: 135, name: StaleTerm} - - {code: 136, name: CappedPositionLost} - - {code: 137, name: IncompatibleShardingConfigVersion} - - {code: 138, name: RemoteOplogStale} - - {code: 139, name: JSInterpreterFailure} - - {code: 140, name: InvalidSSLConfiguration} - - {code: 141, name: SSLHandshakeFailed} - - {code: 142, name: JSUncatchableError} - - {code: 143, name: CursorInUse} - - {code: 144, name: IncompatibleCatalogManager} - - {code: 145, name: PooledConnectionsDropped} - - {code: 146, name: ExceededMemoryLimit} - - {code: 147, name: ZLibError} - - {code: 148, name: ReadConcernMajorityNotEnabled, categories: [VoteAbortError]} - - {code: 149, name: NoConfigMaster} - - {code: 150, name: StaleEpoch, categories: [StaleShardVersionError,NeedRetargettingError]} - - {code: 151, name: OperationCannotBeBatched} - - {code: 152, name: OplogOutOfOrder} - - {code: 153, name: ChunkTooBig} - - {code: 154, name: InconsistentShardIdentity} - - {code: 155, name: CannotApplyOplogWhilePrimary} - - {code: 156, name: OBSOLETE_NeedsDocumentMove} - - {code: 157, name: CanRepairToDowngrade} - - {code: 158, name: MustUpgrade} - - {code: 159, name: DurationOverflow} - - {code: 160, name: MaxStalenessOutOfRange} - - {code: 161, name: IncompatibleCollationVersion} - - {code: 162, name: CollectionIsEmpty} - - {code: 163, name: ZoneStillInUse} - - {code: 164, name: InitialSyncActive} - - {code: 165, name: ViewDepthLimitExceeded} - - {code: 166, name: CommandNotSupportedOnView} - - {code: 167, name: OptionNotSupportedOnView} - - {code: 168, name: InvalidPipelineOperator} - - {code: 169, name: CommandOnShardedViewNotSupportedOnMongod, extra: ResolvedView} - - {code: 170, name: TooManyMatchingDocuments} - - {code: 171, name: CannotIndexParallelArrays} - - {code: 172, name: TransportSessionClosed} - - {code: 173, name: TransportSessionNotFound} - - {code: 174, name: TransportSessionUnknown} - - {code: 175, name: QueryPlanKilled} - - {code: 176, name: FileOpenFailed} - - {code: 177, name: ZoneNotFound} - - {code: 178, name: RangeOverlapConflict} - - {code: 179, name: WindowsPdhError} - - {code: 180, name: BadPerfCounterPath} - - {code: 181, name: AmbiguousIndexKeyPattern} - - {code: 182, name: InvalidViewDefinition} - - {code: 183, name: ClientMetadataMissingField} - - {code: 184, name: ClientMetadataAppNameTooLarge} - - {code: 185, name: ClientMetadataDocumentTooLarge} - - {code: 186, name: ClientMetadataCannotBeMutated} - - {code: 187, name: LinearizableReadConcernError} - - {code: 188, name: IncompatibleServerVersion} - - {code: 189, name: PrimarySteppedDown, categories: [NotMasterError]} - - {code: 190, name: MasterSlaveConnectionFailure} - - {code: 191, name: OBSOLETE_BalancerLostDistributedLock} - - {code: 192, name: FailPointEnabled} - - {code: 193, name: NoShardingEnabled} - - {code: 194, name: BalancerInterrupted} - - {code: 195, name: ViewPipelineMaxSizeExceeded} - - {code: 197, name: InvalidIndexSpecificationOption} - - {code: 198, name: OBSOLETE_ReceivedOpReplyMessage} - - {code: 199, name: ReplicaSetMonitorRemoved} - - {code: 200, name: ChunkRangeCleanupPending} - - {code: 201, name: CannotBuildIndexKeys} - - {code: 202, name: NetworkInterfaceExceededTimeLimit, categories: [ExceededTimeLimitError]} - - {code: 203, name: ShardingStateNotInitialized} - - {code: 204, name: TimeProofMismatch} - - {code: 205, name: ClusterTimeFailsRateLimiter} - - {code: 206, name: NoSuchSession} - - {code: 207, name: InvalidUUID} - - {code: 208, name: TooManyLocks} - - {code: 209, name: StaleClusterTime} - - {code: 210, name: CannotVerifyAndSignLogicalTime} - - {code: 211, name: KeyNotFound} - - {code: 212, name: IncompatibleRollbackAlgorithm} - - {code: 213, name: DuplicateSession} - - {code: 214, name: AuthenticationRestrictionUnmet} - - {code: 215, name: DatabaseDropPending} - - {code: 216, name: ElectionInProgress} - - {code: 217, name: IncompleteTransactionHistory} - - {code: 218, name: UpdateOperationFailed} - - {code: 219, name: FTDCPathNotSet} - - {code: 220, name: FTDCPathAlreadySet} - - {code: 221, name: IndexModified} - - {code: 222, name: CloseChangeStream} - - {code: 223, name: IllegalOpMsgFlag, categories: [ConnectionFatalMessageParseError]} - - {code: 224, name: QueryFeatureNotAllowed} - - {code: 225, name: TransactionTooOld, categories: [VoteAbortError]} - - {code: 226, name: AtomicityFailure} - - {code: 227, name: CannotImplicitlyCreateCollection, + - {code: 0,name: OK} + - {code: 1,name: InternalError} + - {code: 2,name: BadValue} + - {code: 3,name: OBSOLETE_DuplicateKey} + - {code: 4,name: NoSuchKey} + - {code: 5,name: GraphContainsCycle} + - {code: 6,name: HostUnreachable,categories: [NetworkError,RetriableError]} + - {code: 7,name: HostNotFound,categories: [NetworkError,RetriableError]} + - {code: 8,name: UnknownError} + - {code: 9,name: FailedToParse} + - {code: 10,name: CannotMutateObject} + - {code: 11,name: UserNotFound} + - {code: 12,name: UnsupportedFormat} + - {code: 13,name: Unauthorized} + - {code: 14,name: TypeMismatch} + - {code: 15,name: Overflow} + - {code: 16,name: InvalidLength} + - {code: 17,name: ProtocolError} + - {code: 18,name: AuthenticationFailed} + - {code: 19,name: CannotReuseObject} + - {code: 20,name: IllegalOperation} + - {code: 21,name: EmptyArrayOperation} + - {code: 22,name: InvalidBSON} + - {code: 23,name: AlreadyInitialized} + - {code: 24,name: LockTimeout,categories: [Interruption]} + - {code: 25,name: RemoteValidationError} + - {code: 26,name: NamespaceNotFound} + - {code: 27,name: IndexNotFound} + - {code: 28,name: PathNotViable} + - {code: 29,name: NonExistentPath} + - {code: 30,name: InvalidPath} + - {code: 31,name: RoleNotFound} + - {code: 32,name: RolesNotRelated} + - {code: 33,name: PrivilegeNotFound} + - {code: 34,name: CannotBackfillArray} + - {code: 35,name: UserModificationFailed} + - {code: 36,name: RemoteChangeDetected} + - {code: 37,name: FileRenameFailed} + - {code: 38,name: FileNotOpen} + - {code: 39,name: FileStreamFailed} + - {code: 40,name: ConflictingUpdateOperators} + - {code: 41,name: FileAlreadyOpen} + - {code: 42,name: LogWriteFailed} + - {code: 43,name: CursorNotFound} + - {code: 45,name: UserDataInconsistent} + - {code: 46,name: LockBusy} + - {code: 47,name: NoMatchingDocument} + - {code: 48,name: NamespaceExists} + - {code: 49,name: InvalidRoleModification} + - {code: 50,name: MaxTimeMSExpired,categories: [Interruption,ExceededTimeLimitError]} + - {code: 51,name: ManualInterventionRequired} + - {code: 52,name: DollarPrefixedFieldName} + - {code: 53,name: InvalidIdField} + - {code: 54,name: NotSingleValueField} + - {code: 55,name: InvalidDBRef} + - {code: 56,name: EmptyFieldName} + - {code: 57,name: DottedFieldName} + - {code: 58,name: RoleModificationFailed} + - {code: 59,name: CommandNotFound} + - {code: 60,name: OBSOLETE_DatabaseNotFound} + - {code: 61,name: ShardKeyNotFound} + - {code: 62,name: OplogOperationUnsupported} + - {code: 63,name: StaleShardVersion,categories: [StaleShardVersionError,NeedRetargettingError]} + - {code: 64,name: WriteConcernFailed,categories: [WriteConcernError,RetriableError]} + - {code: 65,name: MultipleErrorsOccurred} + - {code: 66,name: ImmutableField} + - {code: 67,name: CannotCreateIndex} + - {code: 68,name: IndexAlreadyExists} + - {code: 69,name: AuthSchemaIncompatible} + - {code: 70,name: ShardNotFound} + - {code: 71,name: ReplicaSetNotFound} + - {code: 72,name: InvalidOptions} + - {code: 73,name: InvalidNamespace} + - {code: 74,name: NodeNotFound} + - {code: 75,name: WriteConcernLegacyOK,categories: [WriteConcernError]} + - {code: 76,name: NoReplicationEnabled} + - {code: 77,name: OperationIncomplete} + - {code: 78,name: CommandResultSchemaViolation} + - {code: 79,name: UnknownReplWriteConcern,categories: [WriteConcernError]} + - {code: 80,name: RoleDataInconsistent} + - {code: 81,name: NoMatchParseContext} + - {code: 82,name: NoProgressMade} + - {code: 83,name: RemoteResultsUnavailable} + - {code: 84,name: DuplicateKeyValue} + - {code: 85,name: IndexOptionsConflict} + - {code: 86,name: IndexKeySpecsConflict} + - {code: 87,name: CannotSplit} + - {code: 88,name: SplitFailed_OBSOLETE} + - {code: 89,name: NetworkTimeout,categories: [NetworkError,RetriableError]} + - {code: 90,name: CallbackCanceled,categories: [CancelationError]} + - {code: 91,name: ShutdownInProgress,categories: [ShutdownError,CancelationError,RetriableError]} + - {code: 92,name: SecondaryAheadOfPrimary} + - {code: 93,name: InvalidReplicaSetConfig} + - {code: 94,name: NotYetInitialized} + - {code: 95,name: NotSecondary} + - {code: 96,name: OperationFailed} + - {code: 97,name: NoProjectionFound} + - {code: 98,name: DBPathInUse} + - {code: 100,name: UnsatisfiableWriteConcern,categories: [WriteConcernError]} + - {code: 101,name: OutdatedClient} + - {code: 102,name: IncompatibleAuditMetadata} + - {code: 103,name: NewReplicaSetConfigurationIncompatible} + - {code: 104,name: NodeNotElectable} + - {code: 105,name: IncompatibleShardingMetadata} + - {code: 106,name: DistributedClockSkewed} + - {code: 107,name: LockFailed} + - {code: 108,name: InconsistentReplicaSetNames} + - {code: 109,name: ConfigurationInProgress} + - {code: 110,name: CannotInitializeNodeWithData} + - {code: 111,name: NotExactValueField} + - {code: 112,name: WriteConflict} + - {code: 113,name: InitialSyncFailure} + - {code: 114,name: InitialSyncOplogSourceMissing} + - {code: 115,name: CommandNotSupported} + - {code: 116,name: DocTooLargeForCapped} + - {code: 117,name: ConflictingOperationInProgress} + - {code: 118,name: NamespaceNotSharded} + - {code: 119,name: InvalidSyncSource} + - {code: 120,name: OplogStartMissing} + - {code: 121,name: DocumentValidationFailure} # Only for the document validator on collections. + - {code: 122,name: OBSOLETE_ReadAfterOptimeTimeout} + - {code: 123,name: NotAReplicaSet} + - {code: 124,name: IncompatibleElectionProtocol} + - {code: 125,name: CommandFailed} + - {code: 126,name: RPCProtocolNegotiationFailed} + - {code: 127,name: UnrecoverableRollbackError} + - {code: 128,name: LockNotFound} + - {code: 129,name: LockStateChangeFailed} + - {code: 130,name: SymbolNotFound} + #- {code: 131,name: RLPInitializationFailed} # Removed in 4.2 + - {code: 132,name: OBSOLETE_ConfigServersInconsistent} + - {code: 133,name: FailedToSatisfyReadPreference} + - {code: 134,name: ReadConcernMajorityNotAvailableYet} + - {code: 135,name: StaleTerm} + - {code: 136,name: CappedPositionLost} + - {code: 137,name: IncompatibleShardingConfigVersion} + - {code: 138,name: RemoteOplogStale} + - {code: 139,name: JSInterpreterFailure} + - {code: 140,name: InvalidSSLConfiguration} + - {code: 141,name: SSLHandshakeFailed} + - {code: 142,name: JSUncatchableError} + - {code: 143,name: CursorInUse} + - {code: 144,name: IncompatibleCatalogManager} + - {code: 145,name: PooledConnectionsDropped} + - {code: 146,name: ExceededMemoryLimit} + - {code: 147,name: ZLibError} + - {code: 148,name: ReadConcernMajorityNotEnabled,categories: [VoteAbortError]} + - {code: 149,name: NoConfigMaster} + - {code: 150,name: StaleEpoch,categories: [StaleShardVersionError,NeedRetargettingError]} + - {code: 151,name: OperationCannotBeBatched} + - {code: 152,name: OplogOutOfOrder} + - {code: 153,name: ChunkTooBig} + - {code: 154,name: InconsistentShardIdentity} + - {code: 155,name: CannotApplyOplogWhilePrimary} + - {code: 156,name: OBSOLETE_NeedsDocumentMove} + - {code: 157,name: CanRepairToDowngrade} + - {code: 158,name: MustUpgrade} + - {code: 159,name: DurationOverflow} + - {code: 160,name: MaxStalenessOutOfRange} + - {code: 161,name: IncompatibleCollationVersion} + - {code: 162,name: CollectionIsEmpty} + - {code: 163,name: ZoneStillInUse} + - {code: 164,name: InitialSyncActive} + - {code: 165,name: ViewDepthLimitExceeded} + - {code: 166,name: CommandNotSupportedOnView} + - {code: 167,name: OptionNotSupportedOnView} + - {code: 168,name: InvalidPipelineOperator} + - {code: 169,name: CommandOnShardedViewNotSupportedOnMongod,extra: ResolvedView} + - {code: 170,name: TooManyMatchingDocuments} + - {code: 171,name: CannotIndexParallelArrays} + - {code: 172,name: TransportSessionClosed} + - {code: 173,name: TransportSessionNotFound} + - {code: 174,name: TransportSessionUnknown} + - {code: 175,name: QueryPlanKilled} + - {code: 176,name: FileOpenFailed} + - {code: 177,name: ZoneNotFound} + - {code: 178,name: RangeOverlapConflict} + - {code: 179,name: WindowsPdhError} + - {code: 180,name: BadPerfCounterPath} + - {code: 181,name: AmbiguousIndexKeyPattern} + - {code: 182,name: InvalidViewDefinition} + - {code: 183,name: ClientMetadataMissingField} + - {code: 184,name: ClientMetadataAppNameTooLarge} + - {code: 185,name: ClientMetadataDocumentTooLarge} + - {code: 186,name: ClientMetadataCannotBeMutated} + - {code: 187,name: LinearizableReadConcernError} + - {code: 188,name: IncompatibleServerVersion} + - {code: 189,name: PrimarySteppedDown,categories: [NotMasterError,RetriableError]} + - {code: 190,name: MasterSlaveConnectionFailure} + - {code: 191,name: OBSOLETE_BalancerLostDistributedLock} + - {code: 192,name: FailPointEnabled} + - {code: 193,name: NoShardingEnabled} + - {code: 194,name: BalancerInterrupted,categories: [RetriableError]} + - {code: 195,name: ViewPipelineMaxSizeExceeded} + - {code: 197,name: InvalidIndexSpecificationOption} + - {code: 198,name: OBSOLETE_ReceivedOpReplyMessage} + - {code: 199,name: ReplicaSetMonitorRemoved} + - {code: 200,name: ChunkRangeCleanupPending} + - {code: 201,name: CannotBuildIndexKeys} + - {code: 202,name: NetworkInterfaceExceededTimeLimit,categories: [ExceededTimeLimitError]} + - {code: 203,name: ShardingStateNotInitialized} + - {code: 204,name: TimeProofMismatch} + - {code: 205,name: ClusterTimeFailsRateLimiter} + - {code: 206,name: NoSuchSession} + - {code: 207,name: InvalidUUID} + - {code: 208,name: TooManyLocks} + - {code: 209,name: StaleClusterTime} + - {code: 210,name: CannotVerifyAndSignLogicalTime} + - {code: 211,name: KeyNotFound} + - {code: 212,name: IncompatibleRollbackAlgorithm} + - {code: 213,name: DuplicateSession} + - {code: 214,name: AuthenticationRestrictionUnmet} + - {code: 215,name: DatabaseDropPending} + - {code: 216,name: ElectionInProgress} + - {code: 217,name: IncompleteTransactionHistory} + - {code: 218,name: UpdateOperationFailed} + - {code: 219,name: FTDCPathNotSet} + - {code: 220,name: FTDCPathAlreadySet} + - {code: 221,name: IndexModified} + - {code: 222,name: CloseChangeStream} + - {code: 223,name: IllegalOpMsgFlag,categories: [ConnectionFatalMessageParseError]} + - {code: 224,name: QueryFeatureNotAllowed} + - {code: 225,name: TransactionTooOld,categories: [VoteAbortError]} + - {code: 226,name: AtomicityFailure} + - {code: 227,name: CannotImplicitlyCreateCollection, extra: CannotImplicitlyCreateCollectionInfo, categories: [NeedRetargettingError]} - - {code: 228, name: SessionTransferIncomplete} - - {code: 229, name: MustDowngrade} - - {code: 230, name: DNSHostNotFound} - - {code: 231, name: DNSProtocolError} - - {code: 232, name: MaxSubPipelineDepthExceeded} - - {code: 233, name: TooManyDocumentSequences, categories: [ConnectionFatalMessageParseError]} - - {code: 234, name: RetryChangeStream} + - {code: 228,name: SessionTransferIncomplete} + - {code: 229,name: MustDowngrade} + - {code: 230,name: DNSHostNotFound} + - {code: 231,name: DNSProtocolError} + - {code: 232,name: MaxSubPipelineDepthExceeded} + - {code: 233,name: TooManyDocumentSequences,categories: [ConnectionFatalMessageParseError]} + - {code: 234,name: RetryChangeStream} # this function or module is not available on this platform or configuration - - {code: 235, name: InternalErrorNotSupported} + - {code: 235,name: InternalErrorNotSupported} - - {code: 236, name: ForTestingErrorExtraInfo, extra: ErrorExtraInfoExample} - - {code: 237, name: CursorKilled, categories: [Interruption]} - - {code: 238, name: NotImplemented} - - {code: 239, name: SnapshotTooOld, categories: [SnapshotError]} - - {code: 240, name: DNSRecordTypeMismatch} - - {code: 241, name: ConversionFailure} - - {code: 242, name: CannotCreateCollection} - - {code: 243, name: IncompatibleWithUpgradedServer} - - {code: 244, name: NOT_YET_AVAILABLE_TransactionAborted} - - {code: 245, name: BrokenPromise} - - {code: 246, name: SnapshotUnavailable, categories: [SnapshotError]} - - {code: 247, name: ProducerConsumerQueueBatchTooLarge} - - {code: 248, name: ProducerConsumerQueueEndClosed} - - {code: 249, name: StaleDbVersion, extra: StaleDbRoutingVersion} - - {code: 250, name: StaleChunkHistory, categories: [SnapshotError]} - - {code: 251, name: NoSuchTransaction, categories: [VoteAbortError]} - - {code: 252, name: ReentrancyNotAllowed} - - {code: 253, name: FreeMonHttpInFlight} - - {code: 254, name: FreeMonHttpTemporaryFailure} - - {code: 255, name: FreeMonHttpPermanentFailure} - - {code: 256, name: TransactionCommitted} - - {code: 257, name: TransactionTooLarge} - - {code: 258, name: UnknownFeatureCompatibilityVersion} - - {code: 259, name: KeyedExecutorRetry} - - {code: 260, name: InvalidResumeToken} - - {code: 261, name: TooManyLogicalSessions} - - {code: 262, name: ExceededTimeLimit, categories: [Interruption,ExceededTimeLimitError]} - - {code: 263, name: OperationNotSupportedInTransaction} - - {code: 264, name: TooManyFilesOpen} - - {code: 265, name: OrphanedRangeCleanUpFailed} - - {code: 266, name: FailPointSetFailed} - - {code: 267, name: PreparedTransactionInProgress} - - {code: 268, name: CannotBackup} - - {code: 269, name: DataModifiedByRepair} - - {code: 270, name: RepairedReplicaSetNode} - - {code: 271, name: JSInterpreterFailureWithStack, extra: JSExceptionInfo} - - {code: 272, name: MigrationConflict, categories: [SnapshotError]} - - {code: 273, name: ProducerConsumerQueueProducerQueueDepthExceeded} - - {code: 274, name: ProducerConsumerQueueConsumed} - - {code: 275, name: ExchangePassthrough} # For exchange execution in aggregation. Do not reuse. - - {code: 276, name: IndexBuildAborted} - - {code: 277, name: AlarmAlreadyFulfilled} - - {code: 278, name: UnsatisfiableCommitQuorum} - - {code: 279, name: ClientDisconnect, categories: [Interruption]} - - {code: 280, name: ChangeStreamFatalError, categories: [NonResumableChangeStreamError]} + - {code: 236,name: ForTestingErrorExtraInfo,extra: ErrorExtraInfoExample} + - {code: 237,name: CursorKilled,categories: [Interruption]} + - {code: 238,name: NotImplemented} + - {code: 239,name: SnapshotTooOld,categories: [SnapshotError]} + - {code: 240,name: DNSRecordTypeMismatch} + - {code: 241,name: ConversionFailure} + - {code: 242,name: CannotCreateCollection} + - {code: 243,name: IncompatibleWithUpgradedServer} + - {code: 244,name: NOT_YET_AVAILABLE_TransactionAborted} + - {code: 245,name: BrokenPromise} + - {code: 246,name: SnapshotUnavailable,categories: [SnapshotError]} + - {code: 247,name: ProducerConsumerQueueBatchTooLarge} + - {code: 248,name: ProducerConsumerQueueEndClosed} + - {code: 249,name: StaleDbVersion,extra: StaleDbRoutingVersion} + - {code: 250,name: StaleChunkHistory,categories: [SnapshotError]} + - {code: 251,name: NoSuchTransaction,categories: [VoteAbortError]} + - {code: 252,name: ReentrancyNotAllowed} + - {code: 253,name: FreeMonHttpInFlight} + - {code: 254,name: FreeMonHttpTemporaryFailure} + - {code: 255,name: FreeMonHttpPermanentFailure} + - {code: 256,name: TransactionCommitted} + - {code: 257,name: TransactionTooLarge} + - {code: 258,name: UnknownFeatureCompatibilityVersion} + - {code: 259,name: KeyedExecutorRetry} + - {code: 260,name: InvalidResumeToken} + - {code: 261,name: TooManyLogicalSessions} + - {code: 262,name: ExceededTimeLimit,categories: [Interruption,ExceededTimeLimitError]} + - {code: 263,name: OperationNotSupportedInTransaction} + - {code: 264,name: TooManyFilesOpen} + - {code: 265,name: OrphanedRangeCleanUpFailed} + - {code: 266,name: FailPointSetFailed} + - {code: 267,name: PreparedTransactionInProgress} + - {code: 268,name: CannotBackup} + - {code: 269,name: DataModifiedByRepair} + - {code: 270,name: RepairedReplicaSetNode} + - {code: 271,name: JSInterpreterFailureWithStack,extra: JSExceptionInfo} + - {code: 272,name: MigrationConflict,categories: [SnapshotError]} + - {code: 273,name: ProducerConsumerQueueProducerQueueDepthExceeded} + - {code: 274,name: ProducerConsumerQueueConsumed} + - {code: 275,name: ExchangePassthrough} # For exchange execution in aggregation. Do not reuse. + - {code: 276,name: IndexBuildAborted} + - {code: 277,name: AlarmAlreadyFulfilled} + - {code: 278,name: UnsatisfiableCommitQuorum} + - {code: 279,name: ClientDisconnect,categories: [Interruption]} + - {code: 280,name: ChangeStreamFatalError,categories: [NonResumableChangeStreamError]} # The two codes below are for internal use only and must never be returned in a network response - - {code: 281, name: TransactionCoordinatorSteppingDown} # Gets converted to InterruptedDueToReplStateChange - - {code: 282, name: TransactionCoordinatorReachedAbortDecision} + - {code: 281,name: TransactionCoordinatorSteppingDown} # Gets converted to InterruptedDueToReplStateChange + - {code: 282,name: TransactionCoordinatorReachedAbortDecision} - - {code: 283, name: WouldChangeOwningShard, extra: WouldChangeOwningShardInfo} - - {code: 284, name: ForTestingErrorExtraInfoWithExtraInfoInNamespace, + - {code: 283,name: WouldChangeOwningShard,extra: WouldChangeOwningShardInfo} + - {code: 284,name: ForTestingErrorExtraInfoWithExtraInfoInNamespace, extra: 'nested::twice::NestedErrorExtraInfoExample'} - - {code: 285, name: IndexBuildAlreadyInProgress} - - {code: 286, name: ChangeStreamHistoryLost, categories: [NonResumableChangeStreamError]} + - {code: 285,name: IndexBuildAlreadyInProgress} + - {code: 286,name: ChangeStreamHistoryLost,categories: [NonResumableChangeStreamError]} # The code below is for internal use only and must never be returned in a network response - - {code: 287, name: TransactionCoordinatorDeadlineTaskCanceled} + - {code: 287,name: TransactionCoordinatorDeadlineTaskCanceled} - - {code: 288, name: ChecksumMismatch, categories: [ConnectionFatalMessageParseError]} + - {code: 288,name: ChecksumMismatch,categories: [ConnectionFatalMessageParseError]} # Internal only code used by WaitForMajorityService. - - {code: 289, name: WaitForMajorityServiceEarlierOpTimeAvailable} + - {code: 289,name: WaitForMajorityServiceEarlierOpTimeAvailable} - - {code: 290, name: TransactionExceededLifetimeLimitSeconds, categories: [ExceededTimeLimitError]} + - {code: 290,name: TransactionExceededLifetimeLimitSeconds,categories: [ExceededTimeLimitError]} # Error codes 4000-8999 are reserved. # Non-sequential error codes for compatibility only) - - {code: 9001, name: SocketException, categories: [NetworkError]} - - {code: 9996, name: OBSOLETE_RecvStaleConfig} - - {code: 10003, name: CannotGrowDocumentInCappedNamespace} - - {code: 10107, name: NotMaster, categories: [NotMasterError]} - - {code: 10334, name: BSONObjectTooLarge} - - {code: 11000, name: DuplicateKey, extra: DuplicateKeyErrorInfo} - - {code: 11600, name: InterruptedAtShutdown, categories: [Interruption,ShutdownError,CancelationError]} - - {code: 11601, name: Interrupted, categories: [Interruption]} - - {code: 11602, name: InterruptedDueToReplStateChange, categories: [Interruption,NotMasterError]} - - {code: 12586, name: BackgroundOperationInProgressForDatabase} - - {code: 12587, name: BackgroundOperationInProgressForNamespace} - - {code: 13104, name: OBSOLETE_PrepareConfigsFailed} - - {code: 13113, name: MergeStageNoMatchingDocument} - - {code: 13297, name: DatabaseDifferCase} - - {code: 13388, name: StaleConfig, + - {code: 9001,name: SocketException,categories: [NetworkError,RetriableError]} + - {code: 9996,name: OBSOLETE_RecvStaleConfig} + - {code: 10003,name: CannotGrowDocumentInCappedNamespace} + - {code: 10107,name: NotMaster,categories: [NotMasterError,RetriableError]} + - {code: 10334,name: BSONObjectTooLarge} + - {code: 11000,name: DuplicateKey,extra: DuplicateKeyErrorInfo} + - {code: 11600,name: InterruptedAtShutdown,categories: [Interruption,ShutdownError,CancelationError,RetriableError]} + - {code: 11601,name: Interrupted,categories: [Interruption]} + - {code: 11602,name: InterruptedDueToReplStateChange,categories: [Interruption,NotMasterError,RetriableError]} + - {code: 12586,name: BackgroundOperationInProgressForDatabase} + - {code: 12587,name: BackgroundOperationInProgressForNamespace} + - {code: 13104,name: OBSOLETE_PrepareConfigsFailed} + - {code: 13113,name: MergeStageNoMatchingDocument} + - {code: 13297,name: DatabaseDifferCase} + - {code: 13388,name: StaleConfig, extra: StaleConfigInfo, - categories: [StaleShardVersionError, NeedRetargettingError]} - - {code: 13435, name: NotMasterNoSlaveOk, categories: [NotMasterError]} - - {code: 13436, name: NotMasterOrSecondary, categories: [NotMasterError]} - - {code: 14031, name: OutOfDiskSpace} - - {code: 17280, name: OSBELETE_KeyTooLong} + categories: [StaleShardVersionError,NeedRetargettingError]} + - {code: 13435,name: NotMasterNoSlaveOk,categories: [NotMasterError,RetriableError]} + - {code: 13436,name: NotMasterOrSecondary,categories: [NotMasterError,RetriableError]} + - {code: 14031,name: OutOfDiskSpace} + - {code: 17280,name: OSBELETE_KeyTooLong} diff --git a/src/mongo/client/fetcher_test.cpp b/src/mongo/client/fetcher_test.cpp index f0fa26cf7b3..d835e89b594 100644 --- a/src/mongo/client/fetcher_test.cpp +++ b/src/mongo/client/fetcher_test.cpp @@ -986,10 +986,8 @@ TEST_F(FetcherTest, ShutdownDuringSecondBatch) { } TEST_F(FetcherTest, FetcherAppliesRetryPolicyToFirstCommandButNotToGetMoreRequests) { - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 3U, - executor::RemoteCommandRequest::kNoTimeout, - {ErrorCodes::BadValue, ErrorCodes::InternalError}); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 3U, executor::RemoteCommandRequest::kNoTimeout); fetcher = std::make_unique<Fetcher>(&getExecutor(), source, @@ -1007,9 +1005,9 @@ TEST_F(FetcherTest, FetcherAppliesRetryPolicyToFirstCommandButNotToGetMoreReques // Retry policy is applied to find command. const BSONObj doc = BSON("_id" << 1); - auto rs = ResponseStatus(ErrorCodes::BadValue, "first", Milliseconds(0)); + auto rs = ResponseStatus(ErrorCodes::HostUnreachable, "first", Milliseconds(0)); processNetworkResponse(rs, ReadyQueueState::kHasReadyRequests, FetcherState::kActive); - rs = ResponseStatus(ErrorCodes::InternalError, "second", Milliseconds(0)); + rs = ResponseStatus(ErrorCodes::SocketException, "second", Milliseconds(0)); processNetworkResponse(rs, ReadyQueueState::kHasReadyRequests, FetcherState::kActive); processNetworkResponse(BSON("cursor" << BSON("id" << 1LL << "ns" << "db.coll" diff --git a/src/mongo/client/remote_command_retry_scheduler.cpp b/src/mongo/client/remote_command_retry_scheduler.cpp index 347c6043a6a..b8eaf0d951f 100644 --- a/src/mongo/client/remote_command_retry_scheduler.cpp +++ b/src/mongo/client/remote_command_retry_scheduler.cpp @@ -42,95 +42,6 @@ namespace mongo { -namespace { - -class RetryPolicyImpl : public RemoteCommandRetryScheduler::RetryPolicy { -public: - RetryPolicyImpl(std::size_t maximumAttempts, - Milliseconds maximumResponseElapsedTotal, - const std::initializer_list<ErrorCodes::Error>& retryableErrors); - std::size_t getMaximumAttempts() const override; - Milliseconds getMaximumResponseElapsedTotal() const override; - bool shouldRetryOnError(ErrorCodes::Error error) const override; - std::string toString() const override; - -private: - std::size_t _maximumAttempts; - Milliseconds _maximumResponseElapsedTotal; - std::vector<ErrorCodes::Error> _retryableErrors; -}; - -RetryPolicyImpl::RetryPolicyImpl(std::size_t maximumAttempts, - Milliseconds maximumResponseElapsedTotal, - const std::initializer_list<ErrorCodes::Error>& retryableErrors) - : _maximumAttempts(maximumAttempts), - _maximumResponseElapsedTotal(maximumResponseElapsedTotal), - _retryableErrors(retryableErrors) { - std::sort(_retryableErrors.begin(), _retryableErrors.end()); -} - -std::string RetryPolicyImpl::toString() const { - str::stream output; - output << "RetryPolicyImpl"; - output << " maxAttempts: " << _maximumAttempts; - output << " maxTimeMillis: " << _maximumResponseElapsedTotal; - - if (_retryableErrors.size() > 0) { - output << "Retryable Errors: "; - for (auto error : _retryableErrors) { - output << error; - } - } - return output; -} - -std::size_t RetryPolicyImpl::getMaximumAttempts() const { - return _maximumAttempts; -} - -Milliseconds RetryPolicyImpl::getMaximumResponseElapsedTotal() const { - return _maximumResponseElapsedTotal; -} - -bool RetryPolicyImpl::shouldRetryOnError(ErrorCodes::Error error) const { - return std::binary_search(_retryableErrors.cbegin(), _retryableErrors.cend(), error); -} - -} // namespace - -const std::initializer_list<ErrorCodes::Error> RemoteCommandRetryScheduler::kNotMasterErrors{ - ErrorCodes::NotMaster, ErrorCodes::NotMasterNoSlaveOk, ErrorCodes::NotMasterOrSecondary}; - -const std::initializer_list<ErrorCodes::Error> RemoteCommandRetryScheduler::kAllRetriableErrors{ - ErrorCodes::NotMaster, - ErrorCodes::NotMasterNoSlaveOk, - ErrorCodes::NotMasterOrSecondary, - // If write concern failed to be satisfied on the remote server, this most probably means that - // some of the secondary nodes were unreachable or otherwise unresponsive, so the call is safe - // to be retried if idempotency can be guaranteed. - ErrorCodes::WriteConcernFailed, - ErrorCodes::HostUnreachable, - ErrorCodes::HostNotFound, - ErrorCodes::NetworkTimeout, - ErrorCodes::PrimarySteppedDown, - ErrorCodes::InterruptedDueToReplStateChange, - ErrorCodes::BalancerInterrupted}; - -std::unique_ptr<RemoteCommandRetryScheduler::RetryPolicy> -RemoteCommandRetryScheduler::makeNoRetryPolicy() { - return makeRetryPolicy(1U, executor::RemoteCommandRequest::kNoTimeout, {}); -} - -std::unique_ptr<RemoteCommandRetryScheduler::RetryPolicy> -RemoteCommandRetryScheduler::makeRetryPolicy( - std::size_t maxAttempts, - Milliseconds maxResponseElapsedTotal, - const std::initializer_list<ErrorCodes::Error>& retryableErrors) { - std::unique_ptr<RetryPolicy> policy = - std::make_unique<RetryPolicyImpl>(maxAttempts, maxResponseElapsedTotal, retryableErrors); - return policy; -} - RemoteCommandRetryScheduler::RemoteCommandRetryScheduler( executor::TaskExecutor* executor, const executor::RemoteCommandRequest& request, diff --git a/src/mongo/client/remote_command_retry_scheduler.h b/src/mongo/client/remote_command_retry_scheduler.h index 82766f7ca18..b4cfe52ef88 100644 --- a/src/mongo/client/remote_command_retry_scheduler.h +++ b/src/mongo/client/remote_command_retry_scheduler.h @@ -33,6 +33,8 @@ #include <initializer_list> #include <memory> +#include <fmt/format.h> + #include "mongo/base/error_codes.h" #include "mongo/executor/task_executor.h" #include "mongo/stdx/condition_variable.h" @@ -64,16 +66,6 @@ public: class RetryPolicy; /** - * List of not master error codes. - */ - static const std::initializer_list<ErrorCodes::Error> kNotMasterErrors; - - /** - * List of retriable error codes. - */ - static const std::initializer_list<ErrorCodes::Error> kAllRetriableErrors; - - /** * Generates a retry policy that will send the remote command request to the source at most * once. */ @@ -81,15 +73,12 @@ public: /** * Creates a retry policy that will send the remote command request at most "maxAttempts". - * This policy will also direct the scheduler to stop retrying if it encounters any of the - * errors in "nonRetryableErrors". * (Requires SERVER-24067) The scheduler will also stop retrying if the total elapsed time * of all failed requests exceeds "maxResponseElapsedTotal". */ - static std::unique_ptr<RetryPolicy> makeRetryPolicy( - std::size_t maxAttempts, - Milliseconds maxResponseElapsedTotal, - const std::initializer_list<ErrorCodes::Error>& retryableErrors); + template <ErrorCategory kCategory> + static std::unique_ptr<RetryPolicy> makeRetryPolicy(std::size_t maxAttempts, + Milliseconds maxResponseElapsedTotal); /** * Creates scheduler but does not schedule any remote command request. @@ -128,6 +117,10 @@ public: std::string toString() const; private: + class NoRetryPolicy; + template <ErrorCategory kCategory> + class RetryPolicyForCategory; + /** * Schedules remote command to be run by the executor. * "requestCount" is number of requests scheduled before calling this function. @@ -207,4 +200,69 @@ public: virtual std::string toString() const = 0; }; +class RemoteCommandRetryScheduler::NoRetryPolicy final + : public RemoteCommandRetryScheduler::RetryPolicy { +public: + std::size_t getMaximumAttempts() const override { + return 1U; + } + + Milliseconds getMaximumResponseElapsedTotal() const override { + return executor::RemoteCommandRequest::kNoTimeout; + } + + bool shouldRetryOnError(ErrorCodes::Error error) const override { + return false; + } + + std::string toString() const override { + return R"!({type: "NoRetryPolicy"})!"; + } +}; + +inline auto RemoteCommandRetryScheduler::makeNoRetryPolicy() -> std::unique_ptr<RetryPolicy> { + return std::make_unique<NoRetryPolicy>(); +} + +template <ErrorCategory kCategory> +class RemoteCommandRetryScheduler::RetryPolicyForCategory final + : public RemoteCommandRetryScheduler::RetryPolicy { +public: + RetryPolicyForCategory(std::size_t maximumAttempts, Milliseconds maximumResponseElapsedTotal) + : _maximumAttempts(maximumAttempts), + _maximumResponseElapsedTotal(maximumResponseElapsedTotal){}; + + std::size_t getMaximumAttempts() const override { + return _maximumAttempts; + } + + Milliseconds getMaximumResponseElapsedTotal() const override { + return _maximumResponseElapsedTotal; + } + + bool shouldRetryOnError(ErrorCodes::Error error) const override { + return ErrorCodes::isA<kCategory>(error); + } + + std::string toString() const override { + using namespace fmt::literals; + return R"!({{type: "RetryPolicyForCategory",categoryIndex: {}, maxAttempts: {}, maxTimeMS: {}}})!"_format( + static_cast<std::underlying_type_t<ErrorCategory>>(kCategory), + _maximumAttempts, + _maximumResponseElapsedTotal.count()); + } + +private: + std::size_t _maximumAttempts; + Milliseconds _maximumResponseElapsedTotal; +}; + +template <ErrorCategory kCategory> +auto RemoteCommandRetryScheduler::makeRetryPolicy(std::size_t maxAttempts, + Milliseconds maxResponseElapsedTotal) + -> std::unique_ptr<RetryPolicy> { + return std::make_unique<RetryPolicyForCategory<kCategory>>(maxAttempts, + maxResponseElapsedTotal); +} + } // namespace mongo diff --git a/src/mongo/client/remote_command_retry_scheduler_test.cpp b/src/mongo/client/remote_command_retry_scheduler_test.cpp index 7940be98674..63932072063 100644 --- a/src/mongo/client/remote_command_retry_scheduler_test.cpp +++ b/src/mongo/client/remote_command_retry_scheduler_test.cpp @@ -184,16 +184,13 @@ TEST_F(RemoteCommandRetrySchedulerTest, MakeSingleShotRetryPolicy) { } TEST_F(RemoteCommandRetrySchedulerTest, MakeRetryPolicy) { - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 5U, - Milliseconds(100), - {ErrorCodes::FailedToParse, ErrorCodes::InvalidNamespace, ErrorCodes::InternalError}); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::Interruption>( + 5U, Milliseconds(100)); ASSERT_EQUALS(5U, policy->getMaximumAttempts()); ASSERT_EQUALS(Milliseconds(100), policy->getMaximumResponseElapsedTotal()); for (int i = 0; i < int(ErrorCodes::MaxError); ++i) { auto error = ErrorCodes::Error(i); - if (error == ErrorCodes::InternalError || error == ErrorCodes::FailedToParse || - error == ErrorCodes::InvalidNamespace) { + if (ErrorCodes::isA<ErrorCategory::Interruption>(error)) { ASSERT_TRUE(policy->shouldRetryOnError(error)); continue; } @@ -271,7 +268,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, InvalidConstruction) { &getExecutor(), request, callback, - RemoteCommandRetryScheduler::makeRetryPolicy(0, Milliseconds(100), {})), + RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 0, Milliseconds(100))), AssertionException, ErrorCodes::BadValue, "policy max attempts cannot be zero"); @@ -282,7 +280,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, InvalidConstruction) { &getExecutor(), request, callback, - RemoteCommandRetryScheduler::makeRetryPolicy(1U, Milliseconds(-100), {})), + RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 1U, Milliseconds(-100))), AssertionException, ErrorCodes::BadValue, "policy max response elapsed total cannot be negative"); @@ -317,8 +316,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, StartupFailsWhenSchedulerIsShutDown) { TEST_F(RemoteCommandRetrySchedulerTest, ShuttingDownExecutorAfterSchedulerStartupInvokesCallbackWithCallbackCanceledError) { CallbackResponseSaver callback; - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 10U, Milliseconds(1), {ErrorCodes::HostUnreachable}); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 10U, Milliseconds(1)); RemoteCommandRetryScheduler scheduler( &getExecutor(), request, std::ref(callback), std::move(policy)); start(&scheduler); @@ -339,8 +338,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, TEST_F(RemoteCommandRetrySchedulerTest, ShuttingDownSchedulerAfterSchedulerStartupInvokesCallbackWithCallbackCanceledError) { CallbackResponseSaver callback; - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 10U, Milliseconds(1), {ErrorCodes::HostUnreachable}); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 10U, Milliseconds(1)); RemoteCommandRetryScheduler scheduler( &getExecutor(), request, std::ref(callback), std::move(policy)); start(&scheduler); @@ -354,8 +353,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, TEST_F(RemoteCommandRetrySchedulerTest, SchedulerInvokesCallbackOnNonRetryableErrorInResponse) { CallbackResponseSaver callback; - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 10U, Milliseconds(1), RemoteCommandRetryScheduler::kNotMasterErrors); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::NotMasterError>( + 10U, Milliseconds(1)); RemoteCommandRetryScheduler scheduler( &getExecutor(), request, std::ref(callback), std::move(policy)); start(&scheduler); @@ -371,8 +370,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, SchedulerInvokesCallbackOnNonRetryableEr TEST_F(RemoteCommandRetrySchedulerTest, SchedulerInvokesCallbackOnFirstSuccessfulResponse) { CallbackResponseSaver callback; - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 10U, Milliseconds(1), {ErrorCodes::HostUnreachable}); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 10U, Milliseconds(1)); RemoteCommandRetryScheduler scheduler( &getExecutor(), request, std::ref(callback), std::move(policy)); start(&scheduler); @@ -390,8 +389,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, SchedulerInvokesCallbackOnFirstSuccessfu TEST_F(RemoteCommandRetrySchedulerTest, SchedulerIgnoresEmbeddedErrorInSuccessfulResponse) { CallbackResponseSaver callback; - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 10U, Milliseconds(1), {ErrorCodes::HostUnreachable}); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 10U, Milliseconds(1)); RemoteCommandRetryScheduler scheduler( &getExecutor(), request, std::ref(callback), std::move(policy)); start(&scheduler); @@ -411,8 +410,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, SchedulerIgnoresEmbeddedErrorInSuccessfu TEST_F(RemoteCommandRetrySchedulerTest, SchedulerInvokesCallbackWithErrorFromExecutorIfScheduleRemoteCommandFailsOnRetry) { CallbackResponseSaver callback; - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 3U, executor::RemoteCommandRequest::kNoTimeout, {ErrorCodes::HostNotFound}); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 3U, executor::RemoteCommandRequest::kNoTimeout); TaskExecutorWithFailureInScheduleRemoteCommand badExecutor(&getExecutor()); RemoteCommandRetryScheduler scheduler( &badExecutor, request, std::ref(callback), std::move(policy)); @@ -432,10 +431,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, TEST_F(RemoteCommandRetrySchedulerTest, SchedulerEnforcesPolicyMaximumAttemptsAndReturnsErrorOfLastFailedRequest) { CallbackResponseSaver callback; - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 3U, - executor::RemoteCommandRequest::kNoTimeout, - RemoteCommandRetryScheduler::kAllRetriableErrors); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 3U, executor::RemoteCommandRequest::kNoTimeout); RemoteCommandRetryScheduler scheduler( &getExecutor(), request, std::ref(callback), std::move(policy)); start(&scheduler); @@ -450,8 +447,8 @@ TEST_F(RemoteCommandRetrySchedulerTest, TEST_F(RemoteCommandRetrySchedulerTest, SchedulerShouldRetryUntilSuccessfulResponseIsReceived) { CallbackResponseSaver callback; - auto policy = RemoteCommandRetryScheduler::makeRetryPolicy( - 3U, executor::RemoteCommandRequest::kNoTimeout, {ErrorCodes::HostNotFound}); + auto policy = RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + 3U, executor::RemoteCommandRequest::kNoTimeout); RemoteCommandRetryScheduler scheduler( &getExecutor(), request, std::ref(callback), std::move(policy)); start(&scheduler); diff --git a/src/mongo/db/repl/collection_cloner.cpp b/src/mongo/db/repl/collection_cloner.cpp index d6c17b38cfd..b081be1fce0 100644 --- a/src/mongo/db/repl/collection_cloner.cpp +++ b/src/mongo/db/repl/collection_cloner.cpp @@ -122,10 +122,9 @@ CollectionCloner::CollectionCloner(executor::TaskExecutor* executor, [this](const executor::TaskExecutor::RemoteCommandCallbackArgs& args) { return _countCallback(args); }, - RemoteCommandRetryScheduler::makeRetryPolicy( + RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( numInitialSyncCollectionCountAttempts.load(), - executor::RemoteCommandRequest::kNoTimeout, - RemoteCommandRetryScheduler::kAllRetriableErrors)), + executor::RemoteCommandRequest::kNoTimeout)), _listIndexesFetcher( _executor, _source, @@ -139,10 +138,9 @@ CollectionCloner::CollectionCloner(executor::TaskExecutor* executor, ReadPreferenceSetting::secondaryPreferredMetadata(), RemoteCommandRequest::kNoTimeout /* find network timeout */, RemoteCommandRequest::kNoTimeout /* getMore network timeout */, - RemoteCommandRetryScheduler::makeRetryPolicy( + RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( numInitialSyncListIndexesAttempts.load(), - executor::RemoteCommandRequest::kNoTimeout, - RemoteCommandRetryScheduler::kAllRetriableErrors)), + executor::RemoteCommandRequest::kNoTimeout)), _indexSpecs(), _documentsToInsert(), _dbWorkTaskRunner(_dbWorkThreadPool), diff --git a/src/mongo/db/repl/database_cloner.cpp b/src/mongo/db/repl/database_cloner.cpp index a0415918a54..5a26e80195d 100644 --- a/src/mongo/db/repl/database_cloner.cpp +++ b/src/mongo/db/repl/database_cloner.cpp @@ -112,22 +112,22 @@ DatabaseCloner::DatabaseCloner(executor::TaskExecutor* executor, _storageInterface(si), _collectionWork(collWork), _onCompletion(std::move(onCompletion)), - _listCollectionsFetcher(_executor, - _source, - _dbname, - createListCollectionsCommandObject(_listCollectionsFilter), - [=](const StatusWith<Fetcher::QueryResponse>& result, - Fetcher::NextAction* nextAction, - BSONObjBuilder* getMoreBob) { - _listCollectionsCallback(result, nextAction, getMoreBob); - }, - ReadPreferenceSetting::secondaryPreferredMetadata(), - RemoteCommandRequest::kNoTimeout /* find network timeout */, - RemoteCommandRequest::kNoTimeout /* getMore network timeout */, - RemoteCommandRetryScheduler::makeRetryPolicy( - numInitialSyncListCollectionsAttempts.load(), - executor::RemoteCommandRequest::kNoTimeout, - RemoteCommandRetryScheduler::kAllRetriableErrors)), + _listCollectionsFetcher( + _executor, + _source, + _dbname, + createListCollectionsCommandObject(_listCollectionsFilter), + [=](const StatusWith<Fetcher::QueryResponse>& result, + Fetcher::NextAction* nextAction, + BSONObjBuilder* getMoreBob) { + _listCollectionsCallback(result, nextAction, getMoreBob); + }, + ReadPreferenceSetting::secondaryPreferredMetadata(), + RemoteCommandRequest::kNoTimeout /* find network timeout */, + RemoteCommandRequest::kNoTimeout /* getMore network timeout */, + RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + numInitialSyncListCollectionsAttempts.load(), + executor::RemoteCommandRequest::kNoTimeout)), _startCollectionCloner([](CollectionCloner& cloner) { return cloner.startup(); }) { // Fetcher throws an exception on null executor. invariant(executor); diff --git a/src/mongo/db/repl/databases_cloner.cpp b/src/mongo/db/repl/databases_cloner.cpp index e2414897339..554acab9651 100644 --- a/src/mongo/db/repl/databases_cloner.cpp +++ b/src/mongo/db/repl/databases_cloner.cpp @@ -209,10 +209,9 @@ Status DatabasesCloner::startup() noexcept { _exec, listDBsReq, [this](const auto& x) { this->_onListDatabaseFinish(x); }, - RemoteCommandRetryScheduler::makeRetryPolicy( + RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( numInitialSyncListDatabasesAttempts.load(), - executor::RemoteCommandRequest::kNoTimeout, - RemoteCommandRetryScheduler::kAllRetriableErrors)); + executor::RemoteCommandRequest::kNoTimeout)); _status = _listDBsScheduler->startup(); if (!_status.isOK()) { diff --git a/src/mongo/db/repl/initial_syncer.cpp b/src/mongo/db/repl/initial_syncer.cpp index dc121c9072c..418899be19c 100644 --- a/src/mongo/db/repl/initial_syncer.cpp +++ b/src/mongo/db/repl/initial_syncer.cpp @@ -675,10 +675,8 @@ Status InitialSyncer::_scheduleGetBeginFetchingOpTime_inlock( ReadPreferenceSetting::secondaryPreferredMetadata(), RemoteCommandRequest::kNoTimeout /* find network timeout */, RemoteCommandRequest::kNoTimeout /* getMore network timeout */, - RemoteCommandRetryScheduler::makeRetryPolicy( - numInitialSyncOplogFindAttempts.load(), - executor::RemoteCommandRequest::kNoTimeout, - RemoteCommandRetryScheduler::kAllRetriableErrors)); + RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + numInitialSyncOplogFindAttempts.load(), executor::RemoteCommandRequest::kNoTimeout)); Status scheduleStatus = _beginFetchingOpTimeFetcher->schedule(); if (!scheduleStatus.isOK()) { _beginFetchingOpTimeFetcher.reset(); @@ -799,10 +797,8 @@ void InitialSyncer::_lastOplogEntryFetcherCallbackForBeginApplyingTimestamp( ReadPreferenceSetting::secondaryPreferredMetadata(), RemoteCommandRequest::kNoTimeout /* find network timeout */, RemoteCommandRequest::kNoTimeout /* getMore network timeout */, - RemoteCommandRetryScheduler::makeRetryPolicy( - numInitialSyncOplogFindAttempts.load(), - executor::RemoteCommandRequest::kNoTimeout, - RemoteCommandRetryScheduler::kAllRetriableErrors)); + RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + numInitialSyncOplogFindAttempts.load(), executor::RemoteCommandRequest::kNoTimeout)); Status scheduleStatus = _fCVFetcher->schedule(); if (!scheduleStatus.isOK()) { _fCVFetcher.reset(); @@ -1441,19 +1437,17 @@ Status InitialSyncer::_scheduleLastOplogEntryFetcher_inlock(Fetcher::CallbackFn BSONObj query = BSON("find" << _opts.remoteOplogNS.coll() << "sort" << BSON("$natural" << -1) << "limit" << 1); - _lastOplogEntryFetcher = - std::make_unique<Fetcher>(_exec, - _syncSource, - _opts.remoteOplogNS.db().toString(), - query, - callback, - ReadPreferenceSetting::secondaryPreferredMetadata(), - RemoteCommandRequest::kNoTimeout /* find network timeout */, - RemoteCommandRequest::kNoTimeout /* getMore network timeout */, - RemoteCommandRetryScheduler::makeRetryPolicy( - numInitialSyncOplogFindAttempts.load(), - executor::RemoteCommandRequest::kNoTimeout, - RemoteCommandRetryScheduler::kAllRetriableErrors)); + _lastOplogEntryFetcher = std::make_unique<Fetcher>( + _exec, + _syncSource, + _opts.remoteOplogNS.db().toString(), + query, + callback, + ReadPreferenceSetting::secondaryPreferredMetadata(), + RemoteCommandRequest::kNoTimeout /* find network timeout */, + RemoteCommandRequest::kNoTimeout /* getMore network timeout */, + RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>( + numInitialSyncOplogFindAttempts.load(), executor::RemoteCommandRequest::kNoTimeout)); Status scheduleStatus = _lastOplogEntryFetcher->schedule(); if (!scheduleStatus.isOK()) { _lastOplogEntryFetcher.reset(); diff --git a/src/mongo/s/client/shard.cpp b/src/mongo/s/client/shard.cpp index e2c751529e2..d2b007a501a 100644 --- a/src/mongo/s/client/shard.cpp +++ b/src/mongo/s/client/shard.cpp @@ -93,10 +93,8 @@ Status Shard::CommandResponse::processBatchWriteResponse( const Milliseconds Shard::kDefaultConfigCommandTimeout = Seconds{30}; bool Shard::shouldErrorBePropagated(ErrorCodes::Error code) { - return std::find(RemoteCommandRetryScheduler::kAllRetriableErrors.begin(), - RemoteCommandRetryScheduler::kAllRetriableErrors.end(), - code) == RemoteCommandRetryScheduler::kAllRetriableErrors.end() && - code != ErrorCodes::NetworkInterfaceExceededTimeLimit; + return !ErrorCodes::isRetriableError(code) && + (code != ErrorCodes::NetworkInterfaceExceededTimeLimit); } Shard::Shard(const ShardId& id) : _id(id) {} diff --git a/src/mongo/s/client/shard_remote.cpp b/src/mongo/s/client/shard_remote.cpp index 7d306e998f9..25f2e1959c0 100644 --- a/src/mongo/s/client/shard_remote.cpp +++ b/src/mongo/s/client/shard_remote.cpp @@ -106,14 +106,21 @@ bool ShardRemote::isRetriableError(ErrorCodes::Error code, RetryPolicy options) return false; } - if (options == RetryPolicy::kNoRetry) { - return false; + switch (options) { + case RetryPolicy::kNoRetry: { + return false; + } break; + + case RetryPolicy::kIdempotent: { + return ErrorCodes::isRetriableError(code); + } break; + + case RetryPolicy::kNotIdempotent: { + return ErrorCodes::isNotMasterError(code); + } break; } - const auto& retriableErrors = options == RetryPolicy::kIdempotent - ? RemoteCommandRetryScheduler::kAllRetriableErrors - : RemoteCommandRetryScheduler::kNotMasterErrors; - return std::find(retriableErrors.begin(), retriableErrors.end(), code) != retriableErrors.end(); + MONGO_UNREACHABLE; } const ConnectionString ShardRemote::getConnString() const { diff --git a/src/mongo/s/query/establish_cursors.cpp b/src/mongo/s/query/establish_cursors.cpp index b97f9026d03..a0ff0f6cb07 100644 --- a/src/mongo/s/query/establish_cursors.cpp +++ b/src/mongo/s/query/establish_cursors.cpp @@ -95,13 +95,9 @@ std::vector<RemoteCursor> establishCursors(OperationContext* opCtx, uassertStatusOK(cursor.getStatus()); } - } catch (const DBException& ex) { + } catch (const ExceptionForCat<ErrorCategory::RetriableError>&) { // Retriable errors are swallowed if 'allowPartialResults' is true. - if (allowPartialResults && - std::find(RemoteCommandRetryScheduler::kAllRetriableErrors.begin(), - RemoteCommandRetryScheduler::kAllRetriableErrors.end(), - ex.code()) != - RemoteCommandRetryScheduler::kAllRetriableErrors.end()) { + if (allowPartialResults) { continue; } throw; // Fail this loop. diff --git a/src/mongo/s/transaction_router.cpp b/src/mongo/s/transaction_router.cpp index 5b791ab0270..81cd77fcab0 100644 --- a/src/mongo/s/transaction_router.cpp +++ b/src/mongo/s/transaction_router.cpp @@ -158,13 +158,6 @@ bool isReadConcernLevelAllowedInTransaction(repl::ReadConcernLevel readConcernLe readConcernLevel == repl::ReadConcernLevel::kLocalReadConcern; } -// Returns if the error code would be considered a retryable error for a retryable write. -bool isRetryableWritesError(ErrorCodes::Error code) { - return std::find(RemoteCommandRetryScheduler::kAllRetriableErrors.begin(), - RemoteCommandRetryScheduler::kAllRetriableErrors.end(), - code) != RemoteCommandRetryScheduler::kAllRetriableErrors.end(); -} - // Returns if a transaction's commit result is unknown based on the given statuses. A result is // considered unknown if it would be given the "UnknownTransactionCommitResult" as defined by the // driver transactions specification or fails with one of the errors for invalid write concern that @@ -176,8 +169,8 @@ bool isRetryableWritesError(ErrorCodes::Error code) { // https://github.com/mongodb/specifications/blob/master/source/transactions/transactions.rst#unknowntransactioncommitresult. bool isCommitResultUnknown(const Status& commitStatus, const Status& commitWCStatus) { if (!commitStatus.isOK()) { - return isRetryableWritesError(commitStatus.code()) || - ErrorCodes::isExceededTimeLimitError(commitStatus.code()) || + return ErrorCodes::isRetriableError(commitStatus) || + ErrorCodes::isExceededTimeLimitError(commitStatus) || commitStatus.code() == ErrorCodes::TransactionTooOld; } diff --git a/src/mongo/util/assert_util_test.cpp b/src/mongo/util/assert_util_test.cpp index 05b33ea3e4b..754d747b5da 100644 --- a/src/mongo/util/assert_util_test.cpp +++ b/src/mongo/util/assert_util_test.cpp @@ -87,9 +87,10 @@ TEST(AssertUtils, UassertNamedCodeWithoutCategories) { ASSERT_NOT_CATCHES(ErrorCodes::BadValue, ExceptionForCat<ErrorCategory::Interruption>); } -// NotMaster - just NotMasterError +// NotMaster - NotMasterError, RetriableError MONGO_STATIC_ASSERT(std::is_same<error_details::ErrorCategoriesFor<ErrorCodes::NotMaster>, - error_details::CategoryList<ErrorCategory::NotMasterError>>()); + error_details::CategoryList<ErrorCategory::NotMasterError, + ErrorCategory::RetriableError>>()); MONGO_STATIC_ASSERT(std::is_base_of<AssertionException, ExceptionFor<ErrorCodes::NotMaster>>()); MONGO_STATIC_ASSERT(!std::is_base_of<ExceptionForCat<ErrorCategory::NetworkError>, ExceptionFor<ErrorCodes::NotMaster>>()); @@ -108,11 +109,12 @@ TEST(AssertUtils, UassertNamedCodeWithOneCategory) { ASSERT_NOT_CATCHES(ErrorCodes::NotMaster, ExceptionForCat<ErrorCategory::Interruption>); } -// InterruptedDueToReplStateChange - NotMasterError and Interruption +// InterruptedDueToReplStateChange - NotMasterError, Interruption, RetriableError MONGO_STATIC_ASSERT( - std::is_same< - error_details::ErrorCategoriesFor<ErrorCodes::InterruptedDueToReplStateChange>, - error_details::CategoryList<ErrorCategory::Interruption, ErrorCategory::NotMasterError>>()); + std::is_same<error_details::ErrorCategoriesFor<ErrorCodes::InterruptedDueToReplStateChange>, + error_details::CategoryList<ErrorCategory::Interruption, + ErrorCategory::NotMasterError, + ErrorCategory::RetriableError>>()); MONGO_STATIC_ASSERT(std::is_base_of<AssertionException, ExceptionFor<ErrorCodes::InterruptedDueToReplStateChange>>()); MONGO_STATIC_ASSERT(!std::is_base_of<ExceptionForCat<ErrorCategory::NetworkError>, |