After the work for
SERVER-35879 goes in, we will already have a way to apply prepare oplog entries during replication recovery. This work includes iterating over the transactions table, finding which sessions had a prepared transaction on them, and applying the prepare oplog entry.
Before we apply these oplog entries, however, we will need to correctly refresh the session state as well as the state of the transaction participant because these will have both been invalidated at the beginning of replication rollback. This must happen before we try to modify the transaction participant (i.e. call unstashTransactionResources or prepareTransaction). There are a couple ways that we can approach this.
First, we could thread a boolean through _recoverFromOplog, _reconstructPreparedTransactions, and applyRecoveredPrepareTransaction. Once we get to applyRecoveredPrepareTransaction, we can check to see if we are recovering from a rollback and refresh the session and transaction participant states.
The second option is to check the OplogApplication mode and if its in OplogApplication::Mode::kRecovering, then refresh the session and transaction participant. Since kRecovering applies to startup recovery AND replication recovery, this would only work if it's safe to do this during startup recovery. During replication recovery, we would not be making any writes to the transactions table, so refreshing the state from disk would not cause us to read those writes and start a new transaction. If the same thing applies to startup recovery, this could be a more elegant solution than the first.
Finally, in both solutions, we would need to introduce a new helper (something like refreshTxnParticipantFromTable) that reconstructs the state of the transaction participant before we cleared it for rollback. This information should be available from the prepare oplog entry.
We would test this via jstests since we would need to induce a rollback and ensure that we have not lost any prepared transactions by the end of the recovery process.