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(); } }
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 }; }
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}"); } } }
/// <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)); }
/// <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)); }
public Task BeginTransaction(NmsTransactionInfo transactionInfo) { if (!SessionInfo.IsTransacted) { throw new IllegalStateException("Non-transacted Session cannot start a TX."); } return(TransactionContext.Begin(transactionInfo)); }
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); }
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}"); } } }
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(); }
public Task Commit(NmsTransactionInfo transactionInfo, NmsTransactionInfo nextTransactionInfo) { throw new NotImplementedException(); }