599 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			YAML
		
	
	
	
	
	
			
		
		
	
	
			599 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			YAML
		
	
	
	
	
	
| description: transactions are correctly pinned to connections for load-balanced clusters
 | |
| 
 | |
| schemaVersion: '1.3'
 | |
| 
 | |
| runOnRequirements:
 | |
|   - topologies: [ load-balanced ]
 | |
| 
 | |
| createEntities:
 | |
|   - client:
 | |
|       id: &client0 client0
 | |
|       useMultipleMongoses: true
 | |
|       observeEvents:
 | |
|         # Do not observe commandSucceededEvent or commandFailedEvent because we cannot guarantee success or failure of
 | |
|         # commands like commitTransaction and abortTransaction in a multi-mongos load-balanced setup.
 | |
|         - commandStartedEvent
 | |
|         - connectionReadyEvent
 | |
|         - connectionClosedEvent
 | |
|         - connectionCheckedOutEvent
 | |
|         - connectionCheckedInEvent
 | |
|   - session:
 | |
|       id: &session0 session0
 | |
|       client: *client0
 | |
|   - database:
 | |
|       id: &database0 database0
 | |
|       client: *client0
 | |
|       databaseName: &database0Name database0Name
 | |
|   - collection:
 | |
|       id: &collection0 collection0
 | |
|       database: *database0
 | |
|       collectionName: &collection0Name coll0
 | |
| 
 | |
| initialData:
 | |
|   - collectionName: *collection0Name
 | |
|     databaseName: *database0Name
 | |
|     documents:
 | |
|       - { _id: 1 }
 | |
|       - { _id: 2 }
 | |
|       - { _id: 3 }
 | |
| 
 | |
| _yamlAnchors:
 | |
|   documents:
 | |
|     - &insertDocument
 | |
|       _id: 4
 | |
| 
 | |
| tests:
 | |
|   - description: sessions are reused in LB mode
 | |
|     operations:
 | |
|       - &nonTransactionalInsert
 | |
|         name: insertOne
 | |
|         object: *collection0
 | |
|         arguments:
 | |
|           document: { x: 1 }
 | |
|       - *nonTransactionalInsert
 | |
|       - name: assertSameLsidOnLastTwoCommands
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
| 
 | |
|   - description: all operations go to the same mongos
 | |
|     operations:
 | |
|       - &startTransaction
 | |
|         name: startTransaction
 | |
|         object: *session0
 | |
|       - &transactionalInsert
 | |
|         name: insertOne
 | |
|         object: *collection0
 | |
|         arguments:
 | |
|           document: { x: 1 }
 | |
|           session: *session0
 | |
|       - &assertConnectionPinned
 | |
|         name: assertNumberConnectionsCheckedOut
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           connections: 1
 | |
|       - *transactionalInsert
 | |
|       - *transactionalInsert
 | |
|       - *transactionalInsert
 | |
|       - *transactionalInsert
 | |
|       - *transactionalInsert
 | |
|       - *assertConnectionPinned
 | |
|       - &commitTransaction
 | |
|         name: commitTransaction
 | |
|         object: *session0
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - &insertStarted
 | |
|             commandStartedEvent:
 | |
|               commandName: insert
 | |
|           - *insertStarted
 | |
|           - *insertStarted
 | |
|           - *insertStarted
 | |
|           - *insertStarted
 | |
|           - *insertStarted
 | |
|           - &commitStarted
 | |
|             commandStartedEvent:
 | |
|               commandName: commitTransaction
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # The connection is never checked back in.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
| 
 | |
|   - description: transaction can be committed multiple times
 | |
|     operations:
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - *assertConnectionPinned
 | |
|       - *commitTransaction
 | |
|       - *assertConnectionPinned
 | |
|       - *commitTransaction
 | |
|       - *commitTransaction
 | |
|       - *commitTransaction
 | |
|       - *assertConnectionPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *commitStarted
 | |
|           - *commitStarted
 | |
|           - *commitStarted
 | |
|           - *commitStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
| 
 | |
|   - description: pinned connection is not released after a non-transient CRUD error
 | |
|     operations:
 | |
|       - name: failPoint
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           failPoint:
 | |
|             configureFailPoint: failCommand
 | |
|             mode: { times: 1 }
 | |
|             data:
 | |
|               failCommands: [ insert ]
 | |
|               errorCode: &nonTransientErrorCode 51 # ManualInterventionRequired
 | |
|       - *startTransaction
 | |
|       - name: insertOne
 | |
|         object: *collection0
 | |
|         arguments:
 | |
|           document: { x: 1 }
 | |
|           session: *session0
 | |
|         expectError: &nonTransientExpectedError
 | |
|           errorCode: *nonTransientErrorCode
 | |
|           errorLabelsOmit: [ TransientTransactionError ]
 | |
|       - *assertConnectionPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for setting the fail point.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the transactional insert.
 | |
|           - connectionCheckedOutEvent: {}
 | |
| 
 | |
|   - description: pinned connection is not released after a non-transient commit error
 | |
|     operations:
 | |
|       - name: failPoint
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           failPoint:
 | |
|             configureFailPoint: failCommand
 | |
|             mode: { times: 1 }
 | |
|             data:
 | |
|               failCommands: [ commitTransaction ]
 | |
|               errorCode: *nonTransientErrorCode
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - name: commitTransaction
 | |
|         object: *session0
 | |
|         expectError: *nonTransientExpectedError
 | |
|       - *assertConnectionPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *commitStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for setting the fail point.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the transactional insert and commit.
 | |
|           - connectionCheckedOutEvent: {}
 | |
| 
 | |
|   # Errors during abort are different than errors during commit and CRUD operations because the pinned connection is
 | |
|   # always released after abort.
 | |
|   - description: pinned connection is released after a non-transient abort error
 | |
|     operations:
 | |
|       - name: failPoint
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           failPoint:
 | |
|             configureFailPoint: failCommand
 | |
|             mode: { times: 1 }
 | |
|             data:
 | |
|               failCommands: [ abortTransaction ]
 | |
|               errorCode: &nonTransientErrorCode 51 # ManualInterventionRequired
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - name: abortTransaction
 | |
|         object: *session0
 | |
|       - &assertConnectionNotPinned
 | |
|         name: assertNumberConnectionsCheckedOut
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           connections: 0
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - &abortStarted
 | |
|             commandStartedEvent:
 | |
|               commandName: abortTransaction
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for setting the fail point.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the transactional insert and abort.
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
| 
 | |
|   - description: pinned connection is released after a transient non-network CRUD error
 | |
|     runOnRequirements:
 | |
|       - serverless: forbid # (CLOUDP-88216) Serverless does not append error labels to errors triggered by failpoints.
 | |
|     operations:
 | |
|       - name: failPoint
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           failPoint:
 | |
|             configureFailPoint: failCommand
 | |
|             mode: { times: 1 }
 | |
|             data:
 | |
|               failCommands: [ insert ]
 | |
|               errorCode: &transientErrorCode 24 # LockTimeout
 | |
|       - *startTransaction
 | |
|       - <<: *transactionalInsert
 | |
|         expectError: &transientExpectedServerError
 | |
|           errorCode: *transientErrorCode
 | |
|           errorLabelsContain: [ TransientTransactionError ]
 | |
|       - *assertConnectionNotPinned
 | |
|       - name: abortTransaction
 | |
|         object: *session0
 | |
|       - *assertConnectionNotPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *abortStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for setting the failpoint.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the insert.
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for abortTransction.
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
| 
 | |
|   - description: pinned connection is released after a transient network CRUD error
 | |
|     runOnRequirements:
 | |
|       - serverless: forbid # (CLOUDP-88216) Serverless does not append error labels to errors triggered by failpoints.
 | |
|     operations:
 | |
|       - name: failPoint
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           failPoint:
 | |
|             configureFailPoint: failCommand
 | |
|             mode: { times: 1 }
 | |
|             data:
 | |
|               failCommands: [ insert ]
 | |
|               closeConnection: true
 | |
|       - *startTransaction
 | |
|       - <<: *transactionalInsert
 | |
|         expectError: &transientExpectedNetworkError
 | |
|           isClientError: true
 | |
|           errorLabelsContain: [ TransientTransactionError ]
 | |
|       - *assertConnectionNotPinned
 | |
|       - name: abortTransaction
 | |
|         object: *session0
 | |
|       - *assertConnectionNotPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *abortStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for setting the failpoint.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the insert.
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           - connectionClosedEvent:
 | |
|               reason: error
 | |
|           # Events for abortTransaction
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
| 
 | |
|   - description: pinned connection is released after a transient non-network commit error
 | |
|     runOnRequirements:
 | |
|       - serverless: forbid # (CLOUDP-88216) Serverless does not append error labels to errors triggered by failpoints.
 | |
|     operations:
 | |
|       - name: failPoint
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           failPoint:
 | |
|             configureFailPoint: failCommand
 | |
|             mode: { times: 1 }
 | |
|             data:
 | |
|               failCommands: [ commitTransaction ]
 | |
|               errorCode: *transientErrorCode
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - <<: *commitTransaction
 | |
|         expectError: *transientExpectedServerError
 | |
|       - *assertConnectionNotPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *commitStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for setting the failpoint.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the insert.
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           # Events for commitTransaction.
 | |
|           - connectionCheckedInEvent: {}
 | |
| 
 | |
|   - description: pinned connection is released after a transient network commit error
 | |
|     operations:
 | |
|       - name: failPoint
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           failPoint:
 | |
|             configureFailPoint: failCommand
 | |
|             mode: { times: 1 }
 | |
|             data:
 | |
|               failCommands: [ commitTransaction ]
 | |
|               closeConnection: true
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - <<: *commitTransaction
 | |
|         # Ignore the result and error because the operation might fail if it targets a new mongos that isn't aware of
 | |
|         # the transaction or the server-side reaper thread closes the transaction first. We only want to assert that
 | |
|         # the operation is retried, which is done via monitoring expectations, so the exact result/error is not
 | |
|         # necessary.
 | |
|         ignoreResultAndError: true
 | |
|       - *assertConnectionNotPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *commitStarted
 | |
|           # The commit will be automatically retried.
 | |
|           - *commitStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for setting the failpoint.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the insert.
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           # Events for the first commitTransaction.
 | |
|           - connectionCheckedInEvent: {}
 | |
|           - connectionClosedEvent:
 | |
|               reason: error
 | |
|           # Events for the commitTransaction retry.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
| 
 | |
|   - description: pinned connection is released after a transient non-network abort error
 | |
|     operations:
 | |
|       - name: failPoint
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           failPoint:
 | |
|             configureFailPoint: failCommand
 | |
|             mode: { times: 1 }
 | |
|             data:
 | |
|               failCommands: [ abortTransaction ]
 | |
|               errorCode: *transientErrorCode
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - name: abortTransaction
 | |
|         object: *session0
 | |
|       - *assertConnectionNotPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *abortStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for setting the failpoint.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the insert.
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           # Events for abortTransaction.
 | |
|           - connectionCheckedInEvent: {}
 | |
| 
 | |
|   - description: pinned connection is released after a transient network abort error
 | |
|     operations:
 | |
|       - name: failPoint
 | |
|         object: testRunner
 | |
|         arguments:
 | |
|           client: *client0
 | |
|           failPoint:
 | |
|             configureFailPoint: failCommand
 | |
|             mode: { times: 1 }
 | |
|             data:
 | |
|               failCommands: [ abortTransaction ]
 | |
|               closeConnection: true
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - name: abortTransaction
 | |
|         object: *session0
 | |
|       - *assertConnectionNotPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *abortStarted
 | |
|           # The abort will be automatically retried.
 | |
|           - *abortStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for setting the failpoint.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the insert.
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           # Events for the first abortTransaction.
 | |
|           - connectionCheckedInEvent: {}
 | |
|           - connectionClosedEvent:
 | |
|               reason: error
 | |
|           # Events for the abortTransaction retry.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
| 
 | |
|   - description: pinned connection is released on successful abort
 | |
|     operations:
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - name: abortTransaction
 | |
|         object: *session0
 | |
|       - *assertConnectionNotPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *abortStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # The insert will create and pin a connection. The abort will use it and then unpin.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
| 
 | |
|   - description: pinned connection is returned when a new transaction is started
 | |
|     operations:
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - *commitTransaction
 | |
|       - *assertConnectionPinned
 | |
|       - *startTransaction
 | |
|       - *assertConnectionNotPinned # startTransaction will unpin the connection.
 | |
|       - *transactionalInsert
 | |
|       - *assertConnectionPinned # The first operation in the new transaction will pin the connection again.
 | |
|       - *commitTransaction
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *commitStarted
 | |
|           - *insertStarted
 | |
|           - *commitStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for the first insert and commit.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           # Events for startTransaction.
 | |
|           - connectionCheckedInEvent: {}
 | |
|           # Events for the second insert and commit.
 | |
|           - connectionCheckedOutEvent: {}
 | |
| 
 | |
|   - description: pinned connection is returned when a non-transaction operation uses the session
 | |
|     operations:
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - *commitTransaction
 | |
|       - *assertConnectionPinned
 | |
|       - *transactionalInsert
 | |
|       # The insert is a non-transactional operation that uses the session, so it unpins the connection.
 | |
|       - *assertConnectionNotPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - *commitStarted
 | |
|           - *insertStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for the first insert and commit.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           # Events for the second insert.
 | |
|           - connectionCheckedInEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           - connectionCheckedInEvent: {}
 | |
| 
 | |
|   - description: a connection can be shared by a transaction and a cursor
 | |
|     operations:
 | |
|       - *startTransaction
 | |
|       - *transactionalInsert
 | |
|       - *assertConnectionPinned
 | |
|       - name: createFindCursor
 | |
|         object: *collection0
 | |
|         arguments:
 | |
|           filter: {}
 | |
|           batchSize: 2
 | |
|           session: *session0
 | |
|         saveResultAsEntity: &cursor0 cursor0
 | |
|       - *assertConnectionPinned
 | |
|       - name: close
 | |
|         object: *cursor0
 | |
|       - *assertConnectionPinned
 | |
|       # Abort the transaction to ensure that the connection is unpinned.
 | |
|       - name: abortTransaction
 | |
|         object: *session0
 | |
|       - *assertConnectionNotPinned
 | |
|     expectEvents:
 | |
|       - client: *client0
 | |
|         events:
 | |
|           - *insertStarted
 | |
|           - commandStartedEvent:
 | |
|               commandName: find
 | |
|           - commandStartedEvent:
 | |
|               commandName: killCursors
 | |
|           - *abortStarted
 | |
|       - client: *client0
 | |
|         eventType: cmap
 | |
|         events:
 | |
|           # Events for the insert, find, and killCursors.
 | |
|           - connectionReadyEvent: {}
 | |
|           - connectionCheckedOutEvent: {}
 | |
|           # Events for abortTransaction.
 | |
|           - connectionCheckedInEvent: {}
 |