private async Task PrivateCommitAsync() { // MCoskun: Note that was TransactionState has moved to Committing it cannot go back to Active. // If this invariant changes, releasing read locks here will cause 2PL to be broken. this.ReleaseReadLocks(); if ((this.IsAtomicOperation == false) && (this.IsWriteTransaction == true)) { this.CommitLatencyWatch.Start(); do { try { if (this.firstOperation != null) { // Commit is invoked after only 1 operation in the transaction. // Convert this to a single operation transaction and avoid replicating a commit record await TransactionalReplicator.BeginTransactionAsync( this, this.firstOperation.MetaData, this.firstOperation.Undo, this.firstOperation.Redo, this.firstOperation.Context, this.firstOperation.StateProviderId).ConfigureAwait(false); } else { await TransactionalReplicator.CommitTransactionAsync(this).ConfigureAwait(false); } StateMachine.OnCommitSuccessful(); return; } catch (Exception e) { var isRetryable = ProcessException(e); if (isRetryable == false) { StateMachine.OnCommitFaulted(); this.ThrowReplicationException(e, false); } } this.TransactionRetryDelay *= RetryBackoffFactor; if (this.TransactionRetryDelay > MaxRetryDelay) { this.TransactionRetryDelay = MaxRetryDelay; } await Task.Delay(this.TransactionRetryDelay).ConfigureAwait(false); } while (true); } // A readonly transaction or atomic operation is considered committed StateMachine.OnCommitSuccessful(); }