public async Task TransactionalSendAndComplete() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { var client = GetClient(); string queueName = scope.QueueName; #region Snippet:ServiceBusTransactionalSend //@@ string connectionString = "<connection_string>"; //@@ string queueName = "<queue_name>"; // since ServiceBusClient implements IAsyncDisposable we create it with "await using" //@@ await using var client = new ServiceBusClient(connectionString); ServiceBusSender sender = client.CreateSender(queueName); await sender.SendAsync(new ServiceBusMessage(Encoding.UTF8.GetBytes("First"))); ServiceBusReceiver receiver = client.CreateReceiver(queueName); ServiceBusReceivedMessage firstMessage = await receiver.ReceiveAsync(); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await sender.SendAsync(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second"))); await receiver.CompleteAsync(firstMessage); ts.Complete(); } #endregion ServiceBusReceivedMessage secondMessage = await receiver.ReceiveAsync(TimeSpan.FromSeconds(5)); Assert.NotNull(secondMessage); await receiver.CompleteAsync(secondMessage); }; }
public async Task TransactionalSendAndReceiveSubscription() { await using (var scope = await ServiceBusScope.CreateWithTopic(enablePartitioning: false, enableSession: false)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.TopicName); ServiceBusMessage message = GetMessage(); await sender.SendAsync(message); ServiceBusReceiver receiver = client.CreateReceiver(scope.TopicName, scope.SubscriptionNames.First()); ServiceBusReceivedMessage received = await receiver.ReceiveAsync(); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await sender.SendAsync(GetMessage()); await receiver.CompleteAsync(received); ts.Complete(); } received = await receiver.ReceiveAsync(TimeSpan.FromSeconds(5)); Assert.NotNull(received); await receiver.CompleteAsync(received); }; }
public async Task TransactionalSendMultipleSessions() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); ServiceBusMessage message1 = GetMessage("session1"); ServiceBusMessage message2 = GetMessage("session2"); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await sender.SendAsync(message1); await sender.ScheduleMessageAsync(message2, DateTimeOffset.UtcNow); ts.Complete(); } ServiceBusReceiver receiver = await client.CreateSessionReceiverAsync(scope.QueueName); ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage); Assert.AreEqual(message1.Body.ToArray(), receivedMessage.Body.ToArray()); await receiver.CompleteAsync(receivedMessage); receiver = await client.CreateSessionReceiverAsync(scope.QueueName); receivedMessage = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage); Assert.AreEqual(message2.Body.ToArray(), receivedMessage.Body.ToArray()); await receiver.CompleteAsync(receivedMessage); }; }
public async Task TransactionalCompleteRollback(bool partitioned, bool sessionEnabled, bool completeInTransactionAfterRollback) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: partitioned, enableSession: sessionEnabled)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); string body = Guid.NewGuid().ToString("N"); ServiceBusMessage message = GetMessage( sessionEnabled ? "sessionId" : null, partitioned ? "sessionId" : null); await sender.SendAsync(message); ServiceBusReceiver receiver = sessionEnabled ? await client.CreateSessionReceiverAsync(scope.QueueName) : client.CreateReceiver(scope.QueueName); var receivedMessage = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage); Assert.AreEqual( message.Body.ToString(), receivedMessage.Body.ToString()); var sequenceNumber = receivedMessage.SequenceNumber; await receiver.DeferAsync(receivedMessage); ServiceBusReceivedMessage deferredMessage = await receiver.ReceiveDeferredMessageAsync(sequenceNumber); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await receiver.CompleteAsync(deferredMessage); } // Adding delay since transaction Commit/Rollback is an asynchronous operation. // Operating on the same message should not be done. await Task.Delay(TimeSpan.FromSeconds(2)); if (completeInTransactionAfterRollback) { using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await receiver.CompleteAsync(deferredMessage); ts.Complete(); } // Adding delay since transaction Commit/Rollback is an asynchronous operation. // Operating on the same message should not be done. await Task.Delay(TimeSpan.FromSeconds(2)); } else { await receiver.CompleteAsync(deferredMessage); } Assert.That( async() => await receiver.CompleteAsync(deferredMessage), Throws.InstanceOf <ServiceBusException>() .And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusException.FailureReason.MessageLockLost)); } }
public async Task CompleteMessage() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; #region Snippet:ServiceBusCompleteMessage //@@ string connectionString = "<connection_string>"; //@@ string queueName = "<queue_name>"; // since ServiceBusClient implements IAsyncDisposable we create it with "await using" await using var client = new ServiceBusClient(connectionString); // create the sender ServiceBusSender sender = client.CreateSender(queueName); // create a message that we can send ServiceBusMessage message = new ServiceBusMessage(Encoding.Default.GetBytes("Hello world!")); // send the message await sender.SendAsync(message); // create a receiver that we can use to receive and settle the message ServiceBusReceiver receiver = client.CreateReceiver(queueName); // the received message is a different type as it contains some service set properties ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(); // complete the message, thereby deleting it from the service await receiver.CompleteAsync(receivedMessage); #endregion Assert.IsNull(await GetNoRetryClient().CreateReceiver(queueName).ReceiveAsync()); } }
public async Task TransactionCommitThrowsUsingDifferentClientsToSameEntity() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { var client1 = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client1.CreateSender(scope.QueueName); var client2 = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusReceiver receiver = client2.CreateReceiver(scope.QueueName); ServiceBusMessage message1 = GetMessage(); ServiceBusMessage message2 = GetMessage(); await sender.SendAsync(message1); ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage); Assert.AreEqual(message1.Body.ToString(), receivedMessage.Body.ToString()); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await receiver.CompleteAsync(receivedMessage); Assert.That( async() => await sender.SendAsync(message2), Throws.InstanceOf <ServiceBusException>()); ts.Complete(); } } }
public async Task CompleteMessageLogsEvents() { var mockLogger = new Mock <ServiceBusEventSource>(); var mockTransportReceiver = new Mock <TransportReceiver>(); var mockConnection = GetMockConnection(mockTransportReceiver); var receiver = new ServiceBusReceiver(mockConnection.Object, "queueName", false, new ServiceBusReceiverOptions()) { Logger = mockLogger.Object }; var msg = new ServiceBusReceivedMessage() { LockTokenGuid = Guid.NewGuid() }; await receiver.CompleteAsync(msg); mockLogger .Verify( log => log.CompleteMessageStart( receiver.Identifier, 1, msg.LockToken), Times.Once); mockLogger .Verify( log => log.CompleteMessageComplete( receiver.Identifier), Times.Once); }
public async Task TransactionalSendCommit(bool partitioned, bool sessionEnabled) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: partitioned, enableSession: sessionEnabled)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); ServiceBusMessage message = GetMessage( sessionEnabled ? "sessionId" : null, partitioned ? "sessionId" : null); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await sender.SendAsync(message); ts.Complete(); } ServiceBusReceiver receiver = sessionEnabled ? await client.CreateSessionReceiverAsync(scope.QueueName) : client.CreateReceiver(scope.QueueName); ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage); Assert.AreEqual(message.Body.ToArray(), receivedMessage.Body.ToArray()); await receiver.CompleteAsync(receivedMessage); }; }
public async Task TransactionCommitWorksUsingSendersAndReceiversFromSameClients() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); ServiceBusReceiver receiver = client.CreateReceiver(scope.QueueName); ServiceBusMessage message1 = GetMessage(); ServiceBusMessage message2 = GetMessage(); await sender.SendAsync(message1); ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage); Assert.AreEqual(message1.Body.ToString(), receivedMessage.Body.ToString()); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await receiver.CompleteAsync(receivedMessage); await sender.SendAsync(message2); ts.Complete(); } // Adding delay since transaction Commit/Rollback is an asynchronous operation. // Operating on the same message should not be done. await Task.Delay(TimeSpan.FromSeconds(2)); // Assert that complete did succeed Assert.That( async() => await receiver.CompleteAsync(receivedMessage), Throws.InstanceOf <ServiceBusException>() .And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusException.FailureReason.MessageLockLost)); // Assert that send did succeed receivedMessage = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage); Assert.AreEqual(message2.Body.ToString(), receivedMessage.Body.ToString()); await receiver.CompleteAsync(receivedMessage); } }
public async Task TransactionRollbackWorksAcrossClientsUsingSameConnectionToSameEntity() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); ServiceBusReceiver receiver = client.CreateReceiver(scope.QueueName); ServiceBusMessage message1 = GetMessage(); ServiceBusMessage message2 = GetMessage(); await sender.SendAsync(message1); ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage); Assert.AreEqual(message1.Body.ToString(), receivedMessage.Body.ToString()); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await receiver.CompleteAsync(receivedMessage.LockToken); await sender.SendAsync(message2); } // Adding delay since transaction Commit/Rollback is an asynchronous operation. // Operating on the same message should not be done. await Task.Delay(TimeSpan.FromSeconds(2)); // Following should succeed without exceptions await receiver.CompleteAsync(receivedMessage.LockToken); // Assert that send failed receivedMessage = await receiver.ReceiveAsync(TimeSpan.FromSeconds(5)); Assert.Null(receivedMessage); } }
public async Task ForwardingEntity() { // queueName--Fwd to--> destinationName--fwd dlq to-- > dqlDestinationName var queueName = Guid.NewGuid().ToString("D").Substring(0, 8); var destinationName = Guid.NewGuid().ToString("D").Substring(0, 8); var dlqDestinationName = Guid.NewGuid().ToString("D").Substring(0, 8); var mgmtClient = new ServiceBusManagementClient(TestEnvironment.ServiceBusConnectionString); await mgmtClient.CreateQueueAsync(dlqDestinationName); await mgmtClient.CreateQueueAsync( new QueueDescription(destinationName) { ForwardDeadLetteredMessagesTo = dlqDestinationName }); await mgmtClient.CreateQueueAsync( new QueueDescription(queueName) { ForwardTo = destinationName }); await using var sbClient = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = sbClient.CreateSender(queueName); await sender.SendAsync(new ServiceBusMessage() { MessageId = "mid" }); ServiceBusReceiver receiver = sbClient.CreateReceiver(destinationName); ServiceBusReceivedMessage msg = await receiver.ReceiveAsync(); Assert.NotNull(msg); Assert.AreEqual("mid", msg.MessageId); await receiver.DeadLetterAsync(msg.LockToken); receiver = sbClient.CreateReceiver(dlqDestinationName); msg = await receiver.ReceiveAsync(); Assert.NotNull(msg); Assert.AreEqual("mid", msg.MessageId); await receiver.CompleteAsync(msg.LockToken); await mgmtClient.DeleteQueueAsync(queueName); await mgmtClient.DeleteQueueAsync(destinationName); await mgmtClient.DeleteQueueAsync(dlqDestinationName); }
public async Task TransactionalSendVia() { await using (var scopeA = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { var scopeB = await ServiceBusScope.CreateWithQueue(enablePartitioning : false, enableSession : false); string connectionString = TestEnvironment.ServiceBusConnectionString; string queueA = scopeA.QueueName; string queueB = scopeB.QueueName; await using var client = GetClient(); #region Snippet:ServiceBusTransactionalSendVia //@@ string connectionString = "<connection_string>"; //@@ string queueA = "<queue_name>"; //@@ string queueB = "<other_queue_name>"; // since ServiceBusClient implements IAsyncDisposable we create it with "await using" //@@ await using var client = new ServiceBusClient(connectionString); ServiceBusSender senderA = client.CreateSender(queueA); await senderA.SendAsync(new ServiceBusMessage(Encoding.UTF8.GetBytes("First"))); ServiceBusSender senderBViaA = client.CreateSender(queueB, new ServiceBusSenderOptions { ViaQueueOrTopicName = queueA }); ServiceBusReceiver receiverA = client.CreateReceiver(queueA); ServiceBusReceivedMessage firstMessage = await receiverA.ReceiveAsync(); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await receiverA.CompleteAsync(firstMessage); await senderBViaA.SendAsync(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second"))); ts.Complete(); } #endregion ServiceBusReceivedMessage secondMessage = await receiverA.ReceiveAsync(TimeSpan.FromSeconds(5)); Assert.Null(secondMessage); ServiceBusReceiver receiverB = client.CreateReceiver(queueB); secondMessage = await receiverB.ReceiveAsync(TimeSpan.FromSeconds(5)); Assert.NotNull(secondMessage); await receiverB.CompleteAsync(secondMessage); }; }
public async Task RenewSessionLock(bool isSessionSpecified) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.GetSender(scope.QueueName); var messageCount = 1; var sessionId1 = "sessionId1"; ServiceBusMessage message = GetMessage(sessionId1); // send another session message before the one we are interested in to make sure that when isSessionSpecified=true, it is being respected await sender.SendAsync(GetMessage("sessionId2")); await sender.SendAsync(message); ServiceBusReceiver receiver = await client.GetSessionReceiverAsync(scope.QueueName, sessionId : isSessionSpecified?sessionId1 : null); var session = receiver.GetSessionManager(); if (isSessionSpecified) { Assert.AreEqual(sessionId1, session.SessionId); } ServiceBusReceivedMessage[] receivedMessages = (await receiver.ReceiveBatchAsync(messageCount)).ToArray(); var receivedMessage = receivedMessages.First(); var firstLockedUntilUtcTime = session.LockedUntil; // Sleeping for 10 seconds... await Task.Delay(10000); await session.RenewSessionLockAsync(); Assert.True(session.LockedUntil >= firstLockedUntilUtcTime + TimeSpan.FromSeconds(10)); // Complete Messages await receiver.CompleteAsync(receivedMessage.LockToken); Assert.AreEqual(messageCount, receivedMessages.Length); if (isSessionSpecified) { Assert.AreEqual(message.MessageId, receivedMessage.MessageId); } var peekedMessage = receiver.PeekAsync(); Assert.IsNull(peekedMessage.Result); } }
public async Task CompleteMessages(bool useSpecificSession) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); var messageCount = 10; var sessionId = "sessionId1"; using ServiceBusMessageBatch batch = await sender.CreateBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount, sessionId).AsEnumerable <ServiceBusMessage>(); await sender.SendAsync(batch); ServiceBusReceiver receiver = await client.CreateSessionReceiverAsync( scope.QueueName, new ServiceBusSessionReceiverOptions { SessionId = useSpecificSession ? sessionId : null }); var messageEnum = messages.GetEnumerator(); var remainingMessages = messageCount; while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveBatchAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId); await receiver.CompleteAsync(item.LockToken); } } Assert.AreEqual(0, remainingMessages); var peekedMessage = receiver.PeekAsync(); Assert.IsNull(peekedMessage.Result); } }
public void CompleteMessageExceptionLogsEvents() { var mockLogger = new Mock <ServiceBusEventSource>(); var mockTransportReceiver = new Mock <TransportReceiver>(); var mockConnection = GetMockConnection(mockTransportReceiver); mockTransportReceiver.Setup( transportReceiver => transportReceiver.CompleteAsync( It.IsAny <string>(), It.IsAny <CancellationToken>())) .Throws(new Exception()); var receiver = new ServiceBusReceiver(mockConnection.Object, "queueName", false, new ServiceBusReceiverOptions()) { Logger = mockLogger.Object }; var msg = new ServiceBusReceivedMessage() { LockTokenGuid = Guid.NewGuid() }; Assert.That( async() => await receiver.CompleteAsync(msg), Throws.InstanceOf <Exception>()); mockLogger .Verify( log => log.CompleteMessageStart( receiver.Identifier, 1, msg.LockToken), Times.Once); mockLogger .Verify( log => log.CompleteMessageException( receiver.Identifier, It.IsAny <string>()), Times.Once); }
public async Task SenderReceiverActivities(bool useSessions) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: useSessions)) { using var listener = new TestDiagnosticListener(EntityScopeFactory.DiagnosticNamespace); var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); string sessionId = null; if (useSessions) { sessionId = "sessionId"; } int numMessages = 5; var msgs = GetMessages(numMessages, sessionId); await sender.SendAsync(msgs); Activity[] sendActivities = AssertSendActivities(useSessions, sender, msgs, listener); ServiceBusReceiver receiver = null; if (useSessions) { receiver = await client.CreateSessionReceiverAsync(scope.QueueName); } else { receiver = client.CreateReceiver(scope.QueueName); } var remaining = numMessages; List <ServiceBusReceivedMessage> receivedMsgs = new List <ServiceBusReceivedMessage>(); while (remaining > 0) { // loop in case we don't receive all messages in one attempt var received = await receiver.ReceiveBatchAsync(remaining); receivedMsgs.AddRange(received); (string Key, object Value, DiagnosticListener)receiveStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ReceiveActivityName + ".Start", receiveStart.Key); Activity receiveActivity = (Activity)receiveStart.Value; AssertCommonTags(receiveActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); CollectionAssert.Contains( receiveActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.RequestedMessageCountAttribute, remaining.ToString())); CollectionAssert.Contains( receiveActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.MessageIdAttribute, string.Join(",", received.Select(m => m.MessageId).ToArray()))); remaining -= received.Count; if (useSessions) { CollectionAssert.Contains( receiveActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SessionIdAttribute, string.Join(",", msgs.Select(m => m.SessionId).Distinct().ToArray()))); } var receiveLinkedActivities = ((IEnumerable <Activity>)receiveActivity.GetType().GetProperty("Links").GetValue(receiveActivity)).ToArray(); for (int i = 0; i < receiveLinkedActivities.Length; i++) { Assert.AreEqual(sendActivities[i].ParentId, receiveLinkedActivities[i].ParentId); } (string Key, object Value, DiagnosticListener)receiveStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ReceiveActivityName + ".Stop", receiveStop.Key); } var msgIndex = 0; var completed = receivedMsgs[msgIndex]; await receiver.CompleteAsync(completed); (string Key, object Value, DiagnosticListener)completeStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.CompleteActivityName + ".Start", completeStart.Key); Activity completeActivity = (Activity)completeStart.Value; AssertCommonTags(completeActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(completeActivity, completed.LockToken); (string Key, object Value, DiagnosticListener)completeStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.CompleteActivityName + ".Stop", completeStop.Key); var deferred = receivedMsgs[++msgIndex]; await receiver.DeferAsync(deferred); (string Key, object Value, DiagnosticListener)deferStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.DeferActivityName + ".Start", deferStart.Key); Activity deferActivity = (Activity)deferStart.Value; AssertCommonTags(deferActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(deferActivity, deferred.LockToken); (string Key, object Value, DiagnosticListener)deferStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.DeferActivityName + ".Stop", deferStop.Key); var deadLettered = receivedMsgs[++msgIndex]; await receiver.DeadLetterAsync(deadLettered); (string Key, object Value, DiagnosticListener)deadLetterStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.DeadLetterActivityName + ".Start", deadLetterStart.Key); Activity deadLetterActivity = (Activity)deadLetterStart.Value; AssertCommonTags(deadLetterActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(deadLetterActivity, deadLettered.LockToken); (string Key, object Value, DiagnosticListener)deadletterStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.DeadLetterActivityName + ".Stop", deadletterStop.Key); var abandoned = receivedMsgs[++msgIndex]; await receiver.AbandonAsync(abandoned); (string Key, object Value, DiagnosticListener)abandonStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.AbandonActivityName + ".Start", abandonStart.Key); Activity abandonActivity = (Activity)abandonStart.Value; AssertCommonTags(abandonActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(abandonActivity, abandoned.LockToken); (string Key, object Value, DiagnosticListener)abandonStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.AbandonActivityName + ".Stop", abandonStop.Key); var receiveDeferMsg = await receiver.ReceiveDeferredMessageAsync(deferred.SequenceNumber); (string Key, object Value, DiagnosticListener)receiveDeferStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ReceiveDeferredActivityName + ".Start", receiveDeferStart.Key); Activity receiveDeferActivity = (Activity)receiveDeferStart.Value; AssertCommonTags(receiveDeferActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); CollectionAssert.Contains( receiveDeferActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.MessageIdAttribute, deferred.MessageId)); CollectionAssert.Contains( receiveDeferActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SequenceNumbersAttribute, deferred.SequenceNumber.ToString())); (string Key, object Value, DiagnosticListener)receiveDeferStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ReceiveDeferredActivityName + ".Stop", receiveDeferStop.Key); // renew lock if (useSessions) { var sessionReceiver = (ServiceBusSessionReceiver)receiver; await sessionReceiver.RenewSessionLockAsync(); (string Key, object Value, DiagnosticListener)renewStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.RenewSessionLockActivityName + ".Start", renewStart.Key); Activity renewActivity = (Activity)renewStart.Value; AssertCommonTags(renewActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); CollectionAssert.Contains( renewActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SessionIdAttribute, "sessionId")); (string Key, object Value, DiagnosticListener)renewStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.RenewSessionLockActivityName + ".Stop", renewStop.Key); // set state var state = Encoding.UTF8.GetBytes("state"); await sessionReceiver.SetSessionStateAsync(state); (string Key, object Value, DiagnosticListener)setStateStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.SetSessionStateActivityName + ".Start", setStateStart.Key); Activity setStateActivity = (Activity)setStateStart.Value; AssertCommonTags(setStateActivity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace); CollectionAssert.Contains( setStateActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SessionIdAttribute, "sessionId")); (string Key, object Value, DiagnosticListener)setStateStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.SetSessionStateActivityName + ".Stop", setStateStop.Key); // get state var getState = await sessionReceiver.GetSessionStateAsync(); Assert.AreEqual(state, getState); (string Key, object Value, DiagnosticListener)getStateStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.GetSessionStateActivityName + ".Start", getStateStart.Key); Activity getStateActivity = (Activity)getStateStart.Value; AssertCommonTags(getStateActivity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace); CollectionAssert.Contains( getStateActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SessionIdAttribute, "sessionId")); (string Key, object Value, DiagnosticListener)getStateStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.GetSessionStateActivityName + ".Stop", getStateStop.Key); } else { await receiver.RenewMessageLockAsync(receivedMsgs[4]); (string Key, object Value, DiagnosticListener)renewStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.RenewMessageLockActivityName + ".Start", renewStart.Key); Activity renewActivity = (Activity)renewStart.Value; AssertCommonTags(renewActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(renewActivity, receivedMsgs[4].LockToken); CollectionAssert.Contains( renewActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.LockedUntilAttribute, receivedMsgs[4].LockedUntil.ToString())); (string Key, object Value, DiagnosticListener)renewStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.RenewMessageLockActivityName + ".Stop", renewStop.Key); } // schedule msgs = GetMessages(numMessages, sessionId); foreach (var msg in msgs) { var seq = await sender.ScheduleMessageAsync(msg, DateTimeOffset.UtcNow.AddMinutes(1)); Assert.IsNotNull(msg.Properties[DiagnosticProperty.DiagnosticIdAttribute]); (string Key, object Value, DiagnosticListener)startMessage = listener.Events.Dequeue(); Activity messageActivity = (Activity)startMessage.Value; AssertCommonTags(messageActivity, sender.EntityPath, sender.FullyQualifiedNamespace); Assert.AreEqual(DiagnosticProperty.MessageActivityName + ".Start", startMessage.Key); (string Key, object Value, DiagnosticListener)stopMessage = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.MessageActivityName + ".Stop", stopMessage.Key); (string Key, object Value, DiagnosticListener)startSchedule = listener.Events.Dequeue(); AssertCommonTags((Activity)startSchedule.Value, sender.EntityPath, sender.FullyQualifiedNamespace); Assert.AreEqual(DiagnosticProperty.ScheduleActivityName + ".Start", startSchedule.Key); (string Key, object Value, DiagnosticListener)stopSchedule = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ScheduleActivityName + ".Stop", stopSchedule.Key); var linkedActivities = ((IEnumerable <Activity>)startSchedule.Value.GetType().GetProperty("Links").GetValue(startSchedule.Value)).ToArray(); Assert.AreEqual(1, linkedActivities.Length); Assert.AreEqual(messageActivity.Id, linkedActivities[0].ParentId); await sender.CancelScheduledMessageAsync(seq); (string Key, object Value, DiagnosticListener)startCancel = listener.Events.Dequeue(); AssertCommonTags((Activity)startCancel.Value, sender.EntityPath, sender.FullyQualifiedNamespace); Assert.AreEqual(DiagnosticProperty.CancelActivityName + ".Start", startCancel.Key); (string Key, object Value, DiagnosticListener)stopCancel = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.CancelActivityName + ".Stop", stopCancel.Key); } // send a batch var batch = await sender.CreateBatchAsync(); for (int i = 0; i < numMessages; i++) { batch.TryAdd(GetMessage(sessionId)); } await sender.SendAsync(batch); AssertSendActivities(useSessions, sender, batch.AsEnumerable <ServiceBusMessage>(), listener); }; }
public async Task TransactionThrowsWhenOperationsOfDifferentPartitionsAreInSameTransaction() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: true, enableSession: false)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); ServiceBusReceiver receiver = client.CreateReceiver(scope.QueueName); string body = Guid.NewGuid().ToString("N"); ServiceBusMessage message1 = GetMessage(partitionKey: "1"); ServiceBusMessage message2 = GetMessage(partitionKey: "2"); // Two send operations to different partitions. var transaction = new CommittableTransaction(); using (TransactionScope ts = new TransactionScope(transaction, TransactionScopeAsyncFlowOption.Enabled)) { await sender.SendAsync(message1); Assert.ThrowsAsync <InvalidOperationException>( async() => await sender.SendAsync(message2)); ts.Complete(); } transaction.Rollback(); // Adding delay since transaction Commit/Rollback is an asynchronous operation. // Operating on the same message should not be done. await Task.Delay(TimeSpan.FromSeconds(2)); // Two complete operations to different partitions. await sender.SendAsync(message1); await sender.SendAsync(message2); ServiceBusReceivedMessage receivedMessage1 = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage1); ServiceBusReceivedMessage receivedMessage2 = await receiver.ReceiveAsync(); Assert.NotNull(receivedMessage2); transaction = new CommittableTransaction(); using (TransactionScope ts = new TransactionScope(transaction, TransactionScopeAsyncFlowOption.Enabled)) { await receiver.CompleteAsync(receivedMessage1); Assert.ThrowsAsync <InvalidOperationException>( async() => await receiver.CompleteAsync(receivedMessage2)); ts.Complete(); } transaction.Rollback(); // Adding delay since transaction Commit/Rollback is an asynchronous operation. // Operating on the same message should not be done. await Task.Delay(TimeSpan.FromSeconds(2)); await receiver.CompleteAsync(receivedMessage1); // the service seems to abandon the message that // triggered the InvalidOperationException // in the transaction Assert.That( async() => await receiver.CompleteAsync(receivedMessage2), Throws.InstanceOf <ServiceBusException>() .And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusException.FailureReason.MessageLockLost)); } }