protected static void VerifyBrokerHasMessagesInQueue(string connectionURI) { INetTxConnectionFactory factory = new NetTxConnectionFactory(ReplaceEnvVar(connectionURI)); using (INetTxConnection connection = factory.CreateNetTxConnection()) { // check messages are present in the queue using (INetTxSession session = connection.CreateNetTxSession()) { IDestination queue = session.GetQueue(testQueueName); using (IMessageConsumer consumer = session.CreateConsumer(queue)) { connection.Start(); for (int i = 0; i < MSG_COUNT; ++i) { IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)); Assert.IsNotNull(msg, "message is not in the queue !"); } consumer.Close(); } } } }
protected void VerifyBrokerQueueCount(int expectedCount, string connectionUri) { using (INetTxConnection connection = dtcFactory.CreateNetTxConnection()) { // check messages are present in the queue using (INetTxSession session = connection.CreateNetTxSession()) { IQueue queue = session.GetQueue(testQueueName); using (IQueueBrowser browser = session.CreateBrowser(queue)) { connection.Start(); int count = 0; IEnumerator enumerator = browser.GetEnumerator(); while (enumerator.MoveNext()) { IMessage msg = enumerator.Current as IMessage; Assert.IsNotNull(msg, "message is not in the queue !"); count++; } // count should match the expected count Assert.AreEqual(expectedCount, count); } } } }
public void TestRedelivered() { // enqueue several messages PurgeDatabase(); PurgeAndFillQueue(); // receive just one using (INetTxConnection connection = dtcFactory.CreateNetTxConnection()) { connection.Start(); using (INetTxSession session = connection.CreateNetTxSession()) { IQueue queue = session.GetQueue(testQueueName); // read message from queue and insert into db table using (IMessageConsumer consumer = session.CreateConsumer(queue)) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew)) using (SqlConnection sqlConnection = new SqlConnection(createDbConnectionString)) using (SqlCommand sqlInsertCommand = new SqlCommand()) { sqlConnection.Open(); sqlInsertCommand.Connection = sqlConnection; ITextMessage message = consumer.Receive(TimeSpan.FromMilliseconds(10000)) as ITextMessage; sqlInsertCommand.CommandText = string.Format("INSERT INTO {0} VALUES ({1})", testTable, Convert.ToInt32(message.Text)); sqlInsertCommand.ExecuteNonQuery(); scoped.Complete(); } } session.Close(); } } // check that others message have status redelivered = false IConnectionFactory checkFactory = new ConnectionFactory(ReplaceEnvVar(connectionUri)); using (IConnection connection = checkFactory.CreateConnection()) { connection.Start(); using (ISession session = connection.CreateSession()) using (IQueueBrowser browser = session.CreateBrowser(session.GetQueue(testQueueName))) { IEnumerator enumerator = browser.GetEnumerator(); while (enumerator.MoveNext()) { IMessage msg = enumerator.Current as IMessage; Assert.IsNotNull(msg, "message is not in the queue!"); Assert.IsFalse(msg.NMSRedelivered, "message is redelivered!"); } } } }
public void TestTransactedProduceAndConsume( [Values("tcp://${activemqhost}:61616")] string baseConnectionURI) { INetTxConnectionFactory factory = new NetTxConnectionFactory(NMSTestSupport.ReplaceEnvVar(baseConnectionURI)); using (INetTxConnection connection = factory.CreateNetTxConnection()) { connection.Start(); using (INetTxSession session = connection.CreateNetTxSession()) { IDestination destination = session.CreateTemporaryQueue(); using (IMessageProducer producer = session.CreateProducer(destination)) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled)) { Assert.IsNotNull(Transaction.Current); for (int i = 0; i < MSG_COUNT; ++i) { producer.Send(session.CreateTextMessage("Hello World")); } scoped.Complete(); } } using (IMessageConsumer consumer = session.CreateConsumer(destination)) { Thread.Sleep(100); using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled)) { for (int i = 0; i < MSG_COUNT; ++i) { IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)); Assert.IsNotNull(msg, "Message was null for index: " + i); } scoped.Complete(); } } // No more messages should be in the Q, non rolled back or otherwise. using (IMessageConsumer consumer = session.CreateConsumer(destination)) { Thread.Sleep(100); IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)); Assert.IsNull(msg, "Message was not null."); } session.Close(); } connection.Close(); } }
public void TestSessionCreateFailsWithInvalidLogLocation() { using (INetTxConnection connection = factory.CreateNetTxConnection()) { connection.ExceptionListener += this.OnException; connection.Start(); NetTxConnection con = connection as NetTxConnection; NetTxRecoveryPolicy policy = con.RecoveryPolicy; (policy.RecoveryLogger as RecoveryFileLogger).Location = nonExistantPath; connection.CreateNetTxSession(); } }
public void MessageShouldEnlistToTheCorrectTransaction() { const int messageCount = 100; const int receiveCount = 100; // enqueue several messages PurgeDatabase(); PurgeAndFillQueue(messageCount); var enlistment = new TestSinglePhaseCommit(); var rand = new Random(); using (INetTxConnection connection = dtcFactory.CreateNetTxConnection()) { connection.Start(); // receive half of total messages using (INetTxSession session = connection.CreateNetTxSession()) { IQueue queue = session.GetQueue(testQueueName); using (IMessageConsumer consumer = session.CreateConsumer(queue)) { for (int i = 0; i < receiveCount; i++) { try { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled)) { ITextMessage message = consumer.Receive(TimeSpan.FromMilliseconds(10000)) as ITextMessage; Transaction.Current.EnlistDurable(Guid.NewGuid(), enlistment, EnlistmentOptions.None); if (rand.Next(2) == 0) { Tracer.InfoFormat("Throwing random Exception for Message {0}", message.NMSMessageId); throw new Exception(); } scoped.Complete(); } } catch { } Assert.False(enlistment.singlePhaseCommit, "No single phase commit should happen."); } } } } }
protected static void ReadFromDbAndProduceToQueueWithCommit(INetTxConnection connection) { IList entries = ExtractDataSet(); using (INetTxSession session = connection.CreateNetTxSession(true)) { IQueue queue = session.GetQueue(testQueueName); // enqueue several messages read from DB try { using (IMessageProducer producer = session.CreateProducer(queue)) { producer.DeliveryMode = MsgDeliveryMode.Persistent; using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew)) using (SqlConnection sqlConnection = new SqlConnection(createDbConnectionString)) { sqlConnection.Open(); Assert.IsNotNull(Transaction.Current); Tracer.DebugFormat("Sending {0} messages to Broker in this TX", entries.Count); foreach (string textBody in entries) { producer.Send(session.CreateTextMessage(textBody)); } using (SqlCommand sqlDeleteCommand = new SqlCommand( string.Format("DELETE FROM {0}", testTable), sqlConnection)) { int count = sqlDeleteCommand.ExecuteNonQuery(); Assert.AreEqual(entries.Count, count, "wrong number of rows deleted"); } scoped.Complete(); } } } catch (Exception e) // exception thrown in TransactionContext.Commit(Enlistment enlistment) { Tracer.Debug("TX;Error from TransactionScope: " + e.Message); Tracer.Debug(e.ToString()); } } }
public void TestTransactedAsyncConsumption() { PurgeDatabase(); PurgeAndFillQueue(MSG_COUNT * BATCH_COUNT); INetTxConnectionFactory factory = new NetTxConnectionFactory(ReplaceEnvVar(connectionURI)); using (INetTxConnection connection = factory.CreateNetTxConnection()) using (NetTxSession session = connection.CreateNetTxSession() as NetTxSession) { IQueue queue = session.GetQueue(testQueueName); IMessageConsumer consumer = session.CreateConsumer(queue); consumer.Listener += AsyncTxAwareOnMessage; // Be carefull, message are dispatched once this is done, so you could receive // a Message outside a TX. We use the awaitBatchProcessingStart event here to // gate te OnMessage callback, once that method returns the Message is ack'd and // no longer has a chance to participate in a TX. connection.Start(); for (int i = 0; i < BATCH_COUNT; ++i) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew)) { session.Enlist(Transaction.Current); batchTxControl = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete); awaitBatchProcessingStart.Set(); scoped.Complete(); } // Reenlisting to fast seems to annoy the DTC. Also since DTC operations are // async we need to allow a little time for lag so that the last TX actually // completes before we start a new one. Thread.Sleep(250); } } // verify sql server has commited the transaction VerifyDatabaseTableIsFull(MSG_COUNT * BATCH_COUNT); // check messages are NOT present in the queue VerifyNoMessagesInQueue(); }
protected static void ReadFromQueueAndInsertIntoDbWithCommit(INetTxConnection connection) { using (INetTxSession session = connection.CreateNetTxSession(true)) { IQueue queue = session.GetQueue(testQueueName); // read message from queue and insert into db table try { using (IMessageConsumer consumer = session.CreateConsumer(queue)) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew)) using (SqlConnection sqlConnection = new SqlConnection(createDbConnectionString)) using (SqlCommand sqlInsertCommand = new SqlCommand()) { sqlConnection.Open(); sqlInsertCommand.Connection = sqlConnection; Assert.IsNotNull(Transaction.Current); for (int i = 0; i < MSG_COUNT; i++) { ITextMessage message = consumer.Receive() as ITextMessage; Assert.IsNotNull(message, "missing message"); sqlInsertCommand.CommandText = string.Format("INSERT INTO {0} VALUES ({1})", testTable, Convert.ToInt32(message.Text)); sqlInsertCommand.ExecuteNonQuery(); } scoped.Complete(); } } } catch (Exception e) { Tracer.Debug("TX;Error from TransactionScope: " + e.Message); Tracer.Debug(e.ToString()); } } }
private static void RunProducer(INetTxConnection connection) { Console.WriteLine("Press 'e' to publish an IEvent, EventMessage, and AnotherEventMessage alternately."); Console.WriteLine("Press 's' to start a saga on MyPublisher."); Console.WriteLine("Press 'c' to send a command to Subscriber1"); Console.WriteLine("Press 'n' to send a command to SubscriberNMS"); Console.WriteLine("Press 'q' to exit"); while (true) { var key = Console.ReadKey(); using (var session = connection.CreateNetTxSession()) { switch (key.KeyChar) { case 'q': return; case 'e': PublishEvent(session); break; case 's': StartSaga(session, "queue://Mypublisher"); break; case 'n': SendCommand(session, "queue://subscribernms", new MyRequestNMS()); break; case 'c': SendCommand(session, "queue://Subscriber1", new MyRequest1()); break; } } } }
protected static void ReadFromQueueAndInsertIntoDbWithScopeAborted(INetTxConnection connection) { using (INetTxSession session = connection.CreateNetTxSession()) { IQueue queue = session.GetQueue(testQueueName); // read message from queue and insert into db table try { using (IMessageConsumer consumer = session.CreateConsumer(queue)) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew)) using (SqlConnection sqlConnection = new SqlConnection(sqlConnectionString)) using (SqlCommand sqlInsertCommand = new SqlCommand()) { sqlConnection.Open(); sqlInsertCommand.Connection = sqlConnection; Assert.IsNotNull(Transaction.Current); for (int i = 0; i < MSG_COUNT; i++) { ITextMessage message = consumer.Receive() as ITextMessage; Assert.IsNotNull(message, "missing message"); sqlInsertCommand.CommandText = string.Format("INSERT INTO {0} VALUES ({1})", testTable, Convert.ToInt32(message.Text)); sqlInsertCommand.ExecuteNonQuery(); } } } } catch (Exception e) { Tracer.Debug("TX;Error from TransactionScope: " + e.Message); Tracer.Debug(e.ToString()); } } }
protected static void ReadFromDbAndProduceToQueueWithScopeAborted(INetTxConnection connection) { IList entries = ExtractDataSet(); using (INetTxSession session = connection.CreateNetTxSession()) { IQueue queue = session.GetQueue(testQueueName); // enqueue several messages read from DB try { using (IMessageProducer producer = session.CreateProducer(queue)) { producer.DeliveryMode = MsgDeliveryMode.Persistent; using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew)) using (SqlConnection sqlConnection = new SqlConnection(sqlConnectionString)) { sqlConnection.Open(); Assert.IsNotNull(Transaction.Current); Tracer.DebugFormat("Sending {0} messages to Broker in this TX", entries.Count); foreach (string textBody in entries) { producer.Send(session.CreateTextMessage(textBody)); } using (SqlCommand sqlDeleteCommand = new SqlCommand( string.Format("DELETE FROM {0}", testTable), sqlConnection)) { int count = sqlDeleteCommand.ExecuteNonQuery(); Assert.AreEqual(entries.Count, count, "wrong number of rows deleted"); } } } } catch (Exception e) { Tracer.Debug("TX;Error from TransactionScope: " + e.Message); Tracer.Debug(e.ToString()); } } }
public void TestTransactedProduceConsumeWithSessionClose( [Values("tcp://${activemqhost}:61616")] string baseConnectionURI) { INetTxConnectionFactory factory = new NetTxConnectionFactory(NMSTestSupport.ReplaceEnvVar(baseConnectionURI)); using (INetTxConnection connection = factory.CreateNetTxConnection()) { connection.Start(); IDestination destination = null; using (INetTxSession session = connection.CreateNetTxSession()) { session.TransactionStartedListener += TransactionStarted; session.TransactionCommittedListener += TransactionCommitted; session.TransactionRolledBackListener += TransactionRolledBack; destination = session.CreateTemporaryQueue(); using (IMessageProducer producer = session.CreateProducer(destination)) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled)) { Assert.IsFalse(this.transactionStarted); Assert.IsNotNull(Transaction.Current); for (int i = 0; i < MSG_COUNT; ++i) { producer.Send(session.CreateTextMessage("Hello World")); } Assert.IsTrue(this.transactionStarted, "A TX should have been started by producing"); scoped.Complete(); } Assert.IsFalse(this.transactionStarted, "TX Should have Committed and cleared Started"); Assert.IsTrue(this.transactionCommitted, "TX Should have Committed"); Assert.IsFalse(this.transactionRolledBack, "TX Should not have Rolledback"); session.Close(); } } using (INetTxSession session = connection.CreateNetTxSession()) { session.TransactionStartedListener += TransactionStarted; session.TransactionCommittedListener += TransactionCommitted; session.TransactionRolledBackListener += TransactionRolledBack; using (IMessageConsumer consumer = session.CreateConsumer(destination)) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled)) { Assert.IsFalse(this.transactionStarted); for (int i = 0; i < MSG_COUNT; ++i) { IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)); Assert.IsNotNull(msg, "Message was null for index: " + i); } Assert.IsTrue(this.transactionStarted, "A TX should have been started by consuming"); scoped.Complete(); } Assert.IsFalse(this.transactionStarted, "TX Should have Committed and cleared Started"); Assert.IsTrue(this.transactionCommitted, "TX Should have Committed"); Assert.IsFalse(this.transactionRolledBack, "TX Should not have Rolledback"); session.Close(); } } using (INetTxSession session = connection.CreateNetTxSession()) { using (IMessageConsumer consumer = session.CreateConsumer(destination)) { for (int i = 0; i < MSG_COUNT; ++i) { IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(50)); Assert.IsNull(msg, "Message was not null for index: " + i); } } session.Close(); } connection.Close(); } }
public void TestTransactedProduceConsumeWithSessionClose( [Values("tcp://${activemqhost}:61616")] string baseConnectionURI) { INetTxConnectionFactory factory = new NetTxConnectionFactory(NMSTestSupport.ReplaceEnvVar(baseConnectionURI)); using (INetTxConnection connection = factory.CreateNetTxConnection()) { connection.Start(); IDestination destination = null; using (INetTxSession session = connection.CreateNetTxSession()) { destination = session.CreateTemporaryQueue(); using (IMessageProducer producer = session.CreateProducer(destination)) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew)) { Assert.IsNotNull(Transaction.Current); for (int i = 0; i < MSG_COUNT; ++i) { producer.Send(session.CreateTextMessage("Hello World")); } scoped.Complete(); } session.Close(); } } using (INetTxSession session = connection.CreateNetTxSession()) { using (IMessageConsumer consumer = session.CreateConsumer(destination)) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew)) { for (int i = 0; i < MSG_COUNT; ++i) { IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)); Assert.IsNotNull(msg, "Message was null for index: " + i); } scoped.Complete(); } session.Close(); } } using (INetTxSession session = connection.CreateNetTxSession()) { using (IMessageConsumer consumer = session.CreateConsumer(destination)) { for (int i = 0; i < MSG_COUNT; ++i) { IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(50)); Assert.IsNull(msg, "Message was not null for index: " + i); } } session.Close(); } connection.Close(); } }
public void TestRedeliveredNoComplete() { const int messageCount = 300; const int receiveCount = 150; // enqueue several messages PurgeDatabase(); PurgeAndFillQueue(messageCount); INetTxConnectionFactory factory = new NetTxConnectionFactory(ReplaceEnvVar(connectionURI)); using (INetTxConnection connection = factory.CreateNetTxConnection()) { // allow no redelivery so that message immediatly goes to the DLQ if first read fails connection.RedeliveryPolicy.MaximumRedeliveries = 0; connection.Start(); // receive half of total messages using (INetTxSession session = connection.CreateNetTxSession()) { IQueue queue = session.GetQueue(testQueueName); // read message from queue and insert into db table using (IMessageConsumer consumer = session.CreateConsumer(queue)) { for (int i = 0; i < receiveCount; i++) { using (TransactionScope scoped = new TransactionScope(TransactionScopeOption.RequiresNew)) using (SqlConnection sqlConnection = new SqlConnection(sqlConnectionString)) using (SqlCommand sqlInsertCommand = new SqlCommand()) { sqlConnection.Open(); sqlInsertCommand.Connection = sqlConnection; ITextMessage message = consumer.Receive(TimeSpan.FromMilliseconds(10000)) as ITextMessage; sqlInsertCommand.CommandText = string.Format("INSERT INTO {0} VALUES ({1})", testTable, Convert.ToInt32(message.Text)); sqlInsertCommand.ExecuteNonQuery(); } } } session.Close(); } } Tracer.Debug("First stage ok"); // check that others message have status redelivered = false IConnectionFactory checkFactory = new ConnectionFactory(ReplaceEnvVar(connectionURI)); using (IConnection connection = checkFactory.CreateConnection()) { connection.Start(); using (ISession session = connection.CreateSession()) using (IQueueBrowser browser = session.CreateBrowser(session.GetQueue(testQueueName))) { IEnumerator enumerator = browser.GetEnumerator(); while (enumerator.MoveNext()) { IMessage msg = enumerator.Current as IMessage; Assert.IsNotNull(msg, "message is not in the queue!"); Assert.IsFalse(msg.NMSRedelivered, "message is redelivered!"); } } } }