示例#1
0
        public async Task Rollback(NmsTransactionInfo transactionInfo, NmsTransactionInfo nextTransactionInfo)
        {
            if (!Equals(transactionInfo.Id, this.current))
            {
                if (!transactionInfo.IsInDoubt && this.current == null)
                {
                    throw new IllegalStateException("Rollback called with no active Transaction.");
                }
                if (!transactionInfo.IsInDoubt && this.current != null)
                {
                    throw new IllegalStateException("Attempt to rollback a transaction other than the current one");
                }
                return;
            }

            Tracer.Debug($"TX Context{this} rolling back current TX[{this.current}]");

            this.current = null;
            await this.coordinator.DischargeAsync(this.txnId, true).Await();


            PostRollback();

            if (nextTransactionInfo != null)
            {
                await Begin(nextTransactionInfo).Await();
            }
        }
示例#2
0
        public async Task Begin(NmsTransactionInfo transactionInfo)
        {
            if (this.current != null)
            {
                throw new NMSException("Begin called while a TX is still Active.");
            }

            if (this.coordinator == null || this.coordinator.IsDetaching())
            {
                this.coordinator = new AmqpTransactionCoordinator(this.session);
            }

            this.txnId = await this.coordinator.DeclareAsync().Await();

            this.current = transactionInfo.Id;
            transactionInfo.ProviderTxId = this.txnId;
            this.cachedTransactedState   = new TransactionalState {
                TxnId = this.txnId
            };
            this.cachedAcceptedState = new TransactionalState
            {
                Outcome = new Accepted(),
                TxnId   = this.txnId
            };
        }
示例#3
0
        public void TestCreateTransactionInfo()
        {
            var info = new NmsTransactionInfo(firstSessionId, firstTxId);

            Assert.AreSame(firstSessionId, info.SessionId);
            Assert.AreSame(firstTxId, info.Id);
            Assert.IsFalse(string.IsNullOrEmpty(info.ToString()));
        }
        public async Task Commit()
        {
            if (IsInDoubt())
            {
                try
                {
                    await Rollback();
                }
                catch (Exception e)
                {
                    Tracer.WarnFormat("Error during rollback of failed TX: ", e);
                }

                throw new TransactionRolledBackException("Transaction failed and has been rolled back.");
            }
            Tracer.Debug($"Commit: {this.transactionInfo.Id}");

            var oldTransactionId = this.transactionInfo.Id;
            var nextTx           = GetNextTransactionInfo();

            try
            {
                await this.connection.Commit(this.transactionInfo, nextTx).ConfigureAwait(false);

                OnTransactionCommitted();
                Reset();
                this.transactionInfo = nextTx;
            }
            catch (NMSException)
            {
                Tracer.Info($"Commit failed for transaction :{oldTransactionId}");
                throw;
            }
            catch (Exception e)
            {
                throw NMSExceptionSupport.Create(e);
            }
            finally
            {
                try
                {
                    // If the provider failed to start a new transaction there will not be
                    // a current provider transaction id present, so we attempt to create
                    // one to recover our state.
                    if (nextTx.ProviderTxId == null)
                    {
                        await Begin().ConfigureAwait(false);
                    }
                }
                catch (Exception e)
                {
                    // TODO
                    // At this point the transacted session is now unrecoverable, we should
                    // probably close it.
                    Tracer.Info($"Failed to start new Transaction after failed rollback of: {oldTransactionId} {e}");
                }
            }
        }
示例#5
0
        /// <summary>
        /// Commit the currently running Transaction.
        /// </summary>
        /// <param name="transactionInfo">the TransactionInfo describing the transaction being committed.</param>
        /// <param name="nextTransactionInfo">the TransactionInfo describing the transaction that should be started immediately.</param>
        /// <exception cref="Exception">throws Exception if an error occurs while performing the operation.</exception>
        public Task Commit(NmsTransactionInfo transactionInfo, NmsTransactionInfo nextTransactionInfo)
        {
            if (!SessionInfo.IsTransacted)
            {
                throw new IllegalStateException("Non-transacted Session cannot commit a TX.");
            }

            return(TransactionContext.Commit(transactionInfo, nextTransactionInfo));
        }
示例#6
0
        /// <summary>
        /// Roll back the currently running Transaction
        /// </summary>
        /// <param name="transactionInfo">The TransactionInfo describing the transaction being rolled back.</param>
        /// <param name="nextTransactionInfo">The TransactionInfo describing the transaction that should be started immediately.</param>
        /// <exception cref="Exception">throws Exception if an error occurs while performing the operation.</exception>
        public Task Rollback(NmsTransactionInfo transactionInfo, NmsTransactionInfo nextTransactionInfo)
        {
            if (!SessionInfo.IsTransacted)
            {
                throw new IllegalStateException("Non-transacted Session cannot rollback a TX.");
            }

            return(TransactionContext.Rollback(transactionInfo, nextTransactionInfo));
        }
示例#7
0
        public Task BeginTransaction(NmsTransactionInfo transactionInfo)
        {
            if (!SessionInfo.IsTransacted)
            {
                throw new IllegalStateException("Non-transacted Session cannot start a TX.");
            }

            return(TransactionContext.Begin(transactionInfo));
        }
示例#8
0
        public void TestEqualsCode()
        {
            var first  = new NmsTransactionInfo(firstSessionId, firstTxId);
            var second = new NmsTransactionInfo(secondSessionId, secondTxId);

            Assert.AreEqual(first, first);
            Assert.AreEqual(second, second);

            Assert.AreNotEqual(first, second);
        }
示例#9
0
        public void TestHashCode()
        {
            var first  = new NmsTransactionInfo(firstSessionId, firstTxId);
            var second = new NmsTransactionInfo(secondSessionId, secondTxId);

            Assert.AreEqual(first.GetHashCode(), first.GetHashCode());
            Assert.AreEqual(second.GetHashCode(), second.GetHashCode());

            Assert.AreNotEqual(first.GetHashCode(), second.GetHashCode());
        }
 public async Task OnConnectionRecovery(IProvider provider)
 {
     if (this.participants.Any())
     {
         Tracer.Debug($"Transaction recovery marking current TX:{this.transactionInfo.Id} as in-doubt.");
         this.transactionInfo.SetInDoubt();
     }
     else
     {
         this.transactionInfo = GetNextTransactionInfo();
         Tracer.Debug($"Transaction recovery creating new TX:{this.transactionInfo.Id} after failover.");
         await provider.CreateResource(this.transactionInfo).ConfigureAwait(false);
     }
 }
        public Task Commit(NmsTransactionInfo transactionInfo, NmsTransactionInfo nextTransactionInfo)
        {
            CheckClosed();

            FailoverRequest request = new FailoverRequest(this, SendTimeout)
            {
                DoTask             = activeProvider => activeProvider.Commit(transactionInfo, nextTransactionInfo),
                Name               = nameof(Commit),
                FailureWhenOffline = true
            };

            request.Run();

            return(request.Task);
        }
        public Task Rollback(NmsTransactionInfo transactionInfo, NmsTransactionInfo nextTransactionInfo)
        {
            CheckClosed();

            FailoverRequest request = new FailoverRequest(this, SendTimeout)
            {
                DoTask = activeProvider => activeProvider.Rollback(transactionInfo, nextTransactionInfo),
                Name   = nameof(Rollback),
                SucceedsWhenOffline = true
            };

            request.Run();

            return(request.Task);
        }
        public async Task Begin()
        {
            this.transactionInfo = GetNextTransactionInfo();

            try
            {
                Reset();
                await this.session.Connection.CreateResource(this.transactionInfo);

                OnTransactionStarted();
                Tracer.Debug($"Begin: {this.transactionInfo.Id}");
            }
            catch (Exception)
            {
                this.transactionInfo.SetInDoubt();
                throw;
            }
        }
        private async Task DoRollback(bool startNewTransaction)
        {
            Tracer.Debug($"Rollback: {this.transactionInfo.Id}");

            var oldTransactionId = this.transactionInfo.Id;
            var nextTx           = startNewTransaction ? GetNextTransactionInfo() : null;

            try
            {
                await this.connection.Rollback(this.transactionInfo, nextTx);

                OnTransactionRolledBack();
                Reset();
                this.transactionInfo = nextTx;
            }
            catch (Exception e)
            {
                Tracer.Info($"Rollback failed for transaction: {oldTransactionId}");
                throw NMSExceptionSupport.Create(e);
            }
            finally
            {
                Reset();

                try
                {
                    // If the provider failed to start a new transaction there will not be
                    // a current provider transaction id present, so we attempt to create
                    // one to recover our state.
                    if (startNewTransaction && nextTx.ProviderTxId == null)
                    {
                        await Begin();
                    }
                }
                catch (Exception e)
                {
                    // TODO
                    // At this point the transacted session is now unrecoverable, we should
                    // probably close it.
                    Tracer.Info($"Failed to start new Transaction after failed rollback of: {this.transactionInfo} {e}");
                }
            }
        }
示例#15
0
        public async Task Commit(NmsTransactionInfo transactionInfo, NmsTransactionInfo nextTransactionInfo)
        {
            if (!Equals(transactionInfo.Id, this.current))
            {
                if (!transactionInfo.IsInDoubt && this.current == null)
                {
                    throw new IllegalStateException("Commit called with no active Transaction.");
                }
                if (!transactionInfo.IsInDoubt && this.current != null)
                {
                    throw new IllegalStateException("Attempt to Commit a transaction other than the current one");
                }
                throw new TransactionRolledBackException("Transaction in doubt and cannot be committed.");
            }

            Tracer.Debug($"TX Context{this} committing back current TX[{this.current}]");

            this.current = null;
            await this.coordinator.DischargeAsync(this.txnId, false).Await();

            PostCommit();

            await Begin(nextTransactionInfo).Await();
        }
示例#16
0
 public Task Commit(NmsTransactionInfo transactionInfo, NmsTransactionInfo nextTransactionInfo)
 {
     throw new NotImplementedException();
 }