/// <inheritdoc />
        public async Task CommitTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            EnsureIsInTransaction(nameof(CommitTransaction));

            try
            {
                if (_currentTransaction.StatementId == 0)
                {
                    return;
                }

                try
                {
                    var firstAttempt = CreateCommitTransactionOperation();
                    await ExecuteEndTransactionOnPrimaryAsync(firstAttempt, cancellationToken).ConfigureAwait(false);

                    return;
                }
                catch (Exception exception) when(ShouldRetryEndTransactionException(exception))
                {
                    // ignore exception and retry
                }

                var secondAttempt = CreateCommitTransactionOperation();
                await ExecuteEndTransactionOnPrimaryAsync(secondAttempt, cancellationToken).ConfigureAwait(false);
            }
            finally
            {
                _currentTransaction = null;
            }
        }
Exemple #2
0
        /// <inheritdoc />
        public void AboutToSendCommand()
        {
            if (_currentTransaction != null)
            {
                switch (_currentTransaction.State)
                {
                case CoreTransactionState.Starting:     // Starting changes to InProgress after the message is sent to the server
                case CoreTransactionState.InProgress:
                    return;

                case CoreTransactionState.Aborted:
                    _currentTransaction = null;
                    break;

                case CoreTransactionState.Committed:
                    // don't set to null when retrying a commit
                    if (!_isCommitTransactionInProgress)
                    {
                        _currentTransaction = null;
                    }
                    return;

                default:
                    throw new Exception($"Unexpected transaction state: {_currentTransaction.State}.");
                }
            }
        }
Exemple #3
0
        // private methods
        private CoreTransaction CreateSubject(
            int statementId        = 0,
            long transactionNumber = 0,
            TransactionOptions transactionOptions = null)
        {
            var subject = new CoreTransaction(transactionNumber, transactionOptions);

            subject.AdvanceStatementId(statementId);
            return(subject);
        }
Exemple #4
0
        public void constructor_should_initialize_instance(
            [Values(1, 2)] long transactionNumber,
            [Values(false, true)] bool nullTransactionOptions)
        {
            var transactionOptions = nullTransactionOptions ? null : new TransactionOptions();

            var result = new CoreTransaction(transactionNumber, transactionOptions);

            result.StatementId.Should().Be(0);
            result.TransactionNumber.Should().Be(transactionNumber);
            result.TransactionOptions.Should().BeSameAs(transactionOptions);
        }
        /// <inheritdoc />
        public void StartTransaction(TransactionOptions transactionOptions = null)
        {
            if (_currentTransaction != null)
            {
                throw new InvalidOperationException("Transaction already in progress.");
            }

            var transactionNumber           = AdvanceTransactionNumber();
            var effectiveTransactionOptions = GetEffectiveTransactionOptions(transactionOptions);
            var transaction = new CoreTransaction(transactionNumber, effectiveTransactionOptions);

            _currentTransaction = transaction;
        }
Exemple #6
0
        /// <inheritdoc />
        public void StartTransaction(TransactionOptions transactionOptions = null)
        {
            EnsureStartTransactionCanBeCalled();

            var transactionNumber           = AdvanceTransactionNumber();
            var effectiveTransactionOptions = GetEffectiveTransactionOptions(transactionOptions);

            if (!effectiveTransactionOptions.WriteConcern.IsAcknowledged)
            {
                throw new InvalidOperationException("Transactions do not support unacknowledged write concerns.");
            }

            _currentTransaction = new CoreTransaction(transactionNumber, effectiveTransactionOptions);
        }
        /// <inheritdoc />
        public void StartTransaction(TransactionOptions transactionOptions = null)
        {
            if (_currentTransaction != null)
            {
                throw new InvalidOperationException("Transaction already in progress.");
            }

            var transactionNumber           = AdvanceTransactionNumber();
            var readConcern                 = transactionOptions?.ReadConcern ?? _options.DefaultTransactionOptions?.ReadConcern ?? ReadConcern.Default;
            var writeConcern                = transactionOptions?.WriteConcern ?? _options.DefaultTransactionOptions?.WriteConcern ?? new WriteConcern();
            var effectiveTransactionOptions = new TransactionOptions(readConcern, writeConcern);
            var transaction                 = new CoreTransaction(transactionNumber, effectiveTransactionOptions);

            _currentTransaction = transaction;
        }
        // public methods
        /// <inheritdoc />
        public void AbortTransaction(CancellationToken cancellationToken = default(CancellationToken))
        {
            EnsureIsInTransaction(nameof(AbortTransaction));

            try
            {
                if (_currentTransaction.StatementId == 0)
                {
                    return;
                }

                try
                {
                    var firstAttempt = CreateAbortTransactionOperation();
                    ExecuteEndTransactionOnPrimary(firstAttempt, cancellationToken);
                    return;
                }
                catch (Exception exception) when(ShouldIgnoreAbortTransactionException(exception))
                {
                    return; // ignore exception and return
                }
                catch (Exception exception) when(ShouldRetryEndTransactionException(exception))
                {
                    // ignore exception and retry
                }
                catch
                {
                    return; // ignore exception and return
                }

                try
                {
                    var secondAttempt = CreateAbortTransactionOperation();
                    ExecuteEndTransactionOnPrimary(secondAttempt, cancellationToken);
                }
                catch
                {
                    return; // ignore exception and return
                }
            }
            finally
            {
                _currentTransaction = null;
            }
        }