|
My impression is that because the logic of whether or not the session is checked out for an operation is based on the command name that we'll want to have an FSM workload which runs all the possible commands that can be run inside of a transaction. The multi_statement_transaction_simple.js and multi_statement_transaction_atomicity_isolation.js FSM workloads only run the update, find, and getMore commands inside of a transaction. I think that we should consider the following approach for work on this ticket:
1. Creating a new multi_statement_transaction_xx.js FSM workload that also runs the insert, delete, findAndModify, and aggregate commands inside of a transaction. My immediate idea would be to $sample a single or small handful of documents from the collection and then in the same transaction have the findAndModify, update, and delete commands act on them. The find and getMore commands (the latter achieved by using a small batch size) can be use to verify the read your writes and repeatable reads properties within the transaction. Given the testing effort that's gone into transactions during the 4.0 development cycle, I believe it unlikely that this new workload would find anything. Instead, the focus should be on having a good base (in that it is reusable) for how we want to write concurrency tests that do "all the things" with transactions.
2. Creating a new multi_statement_transaction_xx_same_session.js FSM workload that extends from the multi_statement_transaction_xx.js FSM workload (via the extendWorkload() function). The workload's $config.setup() function should store a logical session id on the $config.data object either by calling db.getMongo().startSession().getSessionId() or by doing {id: UUID()}. The former may have some caveats around keeping the DriverSession object alive in the main thread to avoid the endSession command being called as part of JavaScript garbage collection. Until SERVER-36404 is addressed, we'll want to serialize the logical session id across threads similar to how we already handle the clusterTime and operationTime.
function setup() {
|
this.lsid = tojson({id: UUID()});
|
}
|
|
function init() {
|
// The parentheses around 'this.lsid' are necessary to force it to be evaluated as a JavaScript
|
// expression (which resolves to an object literal in this case) rather than as a JavaScript
|
// statement.
|
const lsid = eval(`(${this.lsid})`);
|
this.session = db.getMongo().startSession({causalConsistency: false});
|
|
// XXX: Overriding the SessionHolder::getId() function isn't great but may be the most expedient
|
// way to approximate constructing a DriverSession with an existing logical session id. Jason
|
// Carey may have a different idea of what we could do to fold this into the C++ code.
|
this.session._serverSession.handle.getId = () => lsid;
|
}
|
|