description: "retryable-writes insertOne serverErrors" schemaVersion: "1.9" runOnRequirements: - minServerVersion: "4.0" topologies: [ replicaset ] - minServerVersion: "4.1.7" topologies: [ sharded, load-balanced ] createEntities: - client: id: &client0 client0 useMultipleMongoses: false observeEvents: [ commandStartedEvent ] - database: id: &database0 database0 client: *client0 databaseName: &databaseName retryable-writes-tests - collection: id: &collection0 collection0 database: *database0 collectionName: &collectionName coll initialData: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } tests: - description: "InsertOne succeeds after retryable writeConcernError" runOnRequirements: - minServerVersion: "4.3.1" # failCommand errorLabels option operations: - name: failPoint object: testRunner arguments: client: *client0 failPoint: configureFailPoint: failCommand mode: { times: 1 } data: failCommands: [ insert ] errorLabels: [RetryableWriteError] # top-level error labels writeConcernError: code: 91 # ShutdownInProgress errmsg: "Replication is being shut down" - name: insertOne object: *collection0 arguments: document: { _id: 3, x: 33 } expectResult: $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 3 } } expectEvents: - client: *client0 events: - commandStartedEvent: command: insert: *collectionName documents: [{ _id: 3, x: 33 }] commandName: insert databaseName: *databaseName - commandStartedEvent: command: insert: *collectionName documents: [{ _id: 3, x: 33 }] commandName: insert databaseName: *databaseName outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } - { _id: 3, x: 33 } # The write was still applied - description: "RetryableWriteError label is added based on top-level code in pre-4.4 server response" runOnRequirements: - minServerVersion: "4.2" maxServerVersion: "4.2.99" topologies: [ replicaset, sharded ] operations: - name: failPoint object: testRunner arguments: client: *client0 failPoint: configureFailPoint: failCommand # Trigger the fail point twice to allow asserting the error label in # the retry attempt's response. mode: { times: 2 } data: failCommands: [ "insert" ] errorCode: 189 # PrimarySteppedDown - name: insertOne object: *collection0 arguments: document: { _id: 3, x: 33 } expectError: errorLabelsContain: [ "RetryableWriteError" ] expectEvents: - client: *client0 events: - commandStartedEvent: &insertCommandStartedEvent command: insert: *collectionName documents: [{ _id: 3, x: 33 }] commandName: insert databaseName: *databaseName - commandStartedEvent: *insertCommandStartedEvent outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } - description: "RetryableWriteError label is added based on writeConcernError in pre-4.4 mongod response" runOnRequirements: - minServerVersion: "4.2" maxServerVersion: "4.2.99" topologies: [ replicaset ] operations: - name: failPoint object: testRunner arguments: client: *client0 failPoint: configureFailPoint: failCommand # Trigger the fail point twice to allow asserting the error label in # the retry attempt's response. mode: { times: 2 } data: failCommands: [ "insert" ] writeConcernError: code: 91 # ShutdownInProgress errmsg: "Replication is being shut down" - name: insertOne object: *collection0 arguments: document: { _id: 3, x: 33 } expectError: errorLabelsContain: [ "RetryableWriteError" ] expectEvents: - client: *client0 events: - commandStartedEvent: *insertCommandStartedEvent - commandStartedEvent: *insertCommandStartedEvent outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } # writeConcernError doesn't prevent the server from applying the write - { _id: 3, x: 33 } - description: "RetryableWriteError label is not added based on writeConcernError in pre-4.4 mongos response" runOnRequirements: - minServerVersion: "4.2" maxServerVersion: "4.2.99" topologies: [ sharded ] operations: - name: failPoint object: testRunner arguments: client: *client0 failPoint: configureFailPoint: failCommand # Trigger the fail point only once since a RetryableWriteError label # will not be added and the write will not be retried. mode: { times: 1 } data: failCommands: [ "insert" ] writeConcernError: code: 91 # ShutdownInProgress errmsg: "Replication is being shut down" - name: insertOne object: *collection0 arguments: document: { _id: 3, x: 33 } expectError: errorLabelsOmit: [ "RetryableWriteError" ] expectEvents: - client: *client0 events: - commandStartedEvent: *insertCommandStartedEvent outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } # writeConcernError doesn't prevent the server from applying the write - { _id: 3, x: 33 } - description: 'InsertOne succeeds after connection failure' operations: - name: failPoint object: testRunner arguments: client: *client0 failPoint: configureFailPoint: failCommand mode: { times: 1 } data: failCommands: [ insert ] closeConnection: true - object: *collection0 name: insertOne arguments: document: { _id: 3, x: 33 } expectResult: $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 3 } } outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } - { _id: 3, x: 33 } - description: 'InsertOne fails after connection failure when retryWrites option is false' operations: - object: testRunner name: createEntities arguments: entities: - client: id: &client1 client1 useMultipleMongoses: false uriOptions: retryWrites: false - database: id: &database1 database1 client: *client1 databaseName: *databaseName - collection: id: &collection1 collection1 database: *database1 collectionName: *collectionName - name: failPoint object: testRunner arguments: client: *client1 failPoint: configureFailPoint: failCommand mode: { times: 1 } data: failCommands: [ insert ] closeConnection: true - object: *collection1 name: insertOne arguments: document: { _id: 3, x: 33 } expectError: isError: true # If retryWrites is false, the driver should not add the # RetryableWriteError label to the error. errorLabelsOmit: - RetryableWriteError outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } - description: 'InsertOne fails after Interrupted' operations: - name: failPoint object: testRunner arguments: client: *client0 failPoint: configureFailPoint: failCommand mode: { times: 1 } data: failCommands: [ insert ] errorCode: 11601 closeConnection: false - object: *collection0 name: insertOne arguments: document: { _id: 3, x: 33 } expectError: isError: true errorLabelsOmit: - RetryableWriteError outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } - description: 'InsertOne fails after WriteConcernError Interrupted' operations: - name: failPoint object: testRunner arguments: client: *client0 failPoint: configureFailPoint: failCommand mode: { times: 1 } data: failCommands: [ insert ] writeConcernError: code: 11601 errmsg: 'operation was interrupted' - object: *collection0 name: insertOne arguments: document: { _id: 3, x: 33 } expectError: isError: true errorLabelsOmit: - RetryableWriteError outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } - { _id: 3, x: 33 } # The write was still applied. - description: 'InsertOne fails after WriteConcernError WriteConcernFailed' operations: - name: failPoint object: testRunner arguments: client: *client0 failPoint: configureFailPoint: failCommand mode: { times: 1 } data: failCommands: [ insert ] writeConcernError: code: 64 codeName: WriteConcernFailed errmsg: 'waiting for replication timed out' errInfo: wtimeout: true - object: *collection0 name: insertOne arguments: document: { _id: 3, x: 33 } expectError: isError: true errorLabelsOmit: - RetryableWriteError outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 } - { _id: 3, x: 33 } # The write was still applied. - description: 'InsertOne fails with a RetryableWriteError label after two connection failures' operations: - name: failPoint object: testRunner arguments: client: *client0 failPoint: configureFailPoint: failCommand mode: { times: 2 } data: failCommands: [ insert ] closeConnection: true - object: *collection0 name: insertOne arguments: document: { _id: 3, x: 33 } expectError: isError: true errorLabelsContain: - RetryableWriteError outcome: - collectionName: *collectionName databaseName: *databaseName documents: - { _id: 1, x: 11 } - { _id: 2, x: 22 }