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 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 <ServiceBusReceivedMessage> ReceiveMessageAsync(CancellationToken stoppingToken) { try { var message = await _serviceBusReceiver.ReceiveAsync(); return(message); } catch (ServiceBusException ex) { _logger.LogError($"{nameof(ServiceBusException)} - error details: {ex.Message}"); throw; } }
public void ReceiveMessageExceptionLogsEvents() { var mockLogger = new Mock <ServiceBusEventSource>(); var mockTransportReceiver = new Mock <TransportReceiver>(); var mockConnection = GetMockConnection(mockTransportReceiver); mockTransportReceiver.Setup( transportReceiver => transportReceiver.ReceiveBatchAsync( 1, It.IsAny <TimeSpan?>(), It.IsAny <CancellationToken>())) .Throws(new Exception()); var receiver = new ServiceBusReceiver(mockConnection.Object, "queueName", false, new ServiceBusReceiverOptions()) { Logger = mockLogger.Object }; Assert.That( async() => await receiver.ReceiveAsync(), Throws.InstanceOf <Exception>()); mockLogger .Verify( log => log.ReceiveMessageStart( receiver.Identifier, 1), Times.Once); mockLogger .Verify( log => log.ReceiveMessageException( receiver.Identifier, It.IsAny <string>()), Times.Once); }
public async Task DeadLetterMessage() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; // 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); #region Snippet:ServiceBusDeadLetterMessage ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(); // deadletter the message, thereby preventing the message from being received again without receiving from the dead letter queue. await receiver.DeadLetterAsync(receivedMessage); // receive the dead lettered message with receiver scoped to the dead letter queue. ServiceBusReceiver dlqReceiver = client.CreateDeadLetterReceiver(queueName); ServiceBusReceivedMessage dlqMessage = await dlqReceiver.ReceiveAsync(); #endregion Assert.IsNotNull(dlqMessage); } }
public async Task SendAndReceiveMessage() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; #region Snippet:ServiceBusSendAndReceive //@@ 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.UTF8.GetBytes("Hello world!")); // send the message await sender.SendAsync(message); // create a receiver that we can use to receive 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(); // get the message body as a string string body = Encoding.UTF8.GetString(receivedMessage.Body.ToArray()); Console.WriteLine(body); #endregion Assert.AreEqual(Encoding.UTF8.GetBytes("Hello world!"), receivedMessage.Body.ToArray()); } }
public async Task TransactionalSendRollback(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); // not completing the transaction } ServiceBusReceiver receiver = sessionEnabled ? await client.CreateSessionReceiverAsync( scope.QueueName, new ServiceBusSessionReceiverOptions { SessionId = "sessionId" }) : client.CreateReceiver(scope.QueueName); ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(TimeSpan.FromSeconds(5)); Assert.IsNull(receivedMessage); }; }
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 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 AbandonMessage() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; // 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); #region Snippet:ServiceBusAbandonMessage ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(); // abandon the message, thereby releasing the lock and allowing it to be received again by this or other receivers await receiver.AbandonAsync(receivedMessage); #endregion Assert.IsNotNull(GetNoRetryClient().CreateReceiver(queueName).ReceiveAsync()); } }
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 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 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 ReceiveSingleMessageLogsEvents() { var mockLogger = new Mock <ServiceBusEventSource>(); var mockTransportReceiver = new Mock <TransportReceiver>(); var mockConnection = GetMockConnection(mockTransportReceiver); mockTransportReceiver.Setup( transportReceiver => transportReceiver.ReceiveBatchAsync( 1, It.IsAny <TimeSpan?>(), It.IsAny <CancellationToken>())) .Returns( Task.FromResult((IList <ServiceBusReceivedMessage>) new List <ServiceBusReceivedMessage> { new ServiceBusReceivedMessage() })); var receiver = new ServiceBusReceiver(mockConnection.Object, "queueName", false, new ServiceBusReceiverOptions()) { Logger = mockLogger.Object }; await receiver.ReceiveAsync(); mockLogger .Verify( log => log.ReceiveMessageStart( receiver.Identifier, 1), Times.Once); mockLogger .Verify( log => log.ReceiveMessageComplete( receiver.Identifier, 1), Times.Once); }
public async Task DeferMessage() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; // 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.UTF8.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); #region Snippet:ServiceBusDeferMessage ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveAsync(); // defer the message, thereby preventing the message from being received again without using // the received deferred message API. await receiver.DeferAsync(receivedMessage); // receive the deferred message by specifying the service set sequence number of the original // received message ServiceBusReceivedMessage deferredMessage = await receiver.ReceiveDeferredMessageAsync(receivedMessage.SequenceNumber); #endregion Assert.IsNotNull(deferredMessage); } }
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)); } }
public async Task GetSubscriptionRuntimeInfoTest() { var topicName = nameof(GetSubscriptionRuntimeInfoTest).ToLower() + Guid.NewGuid().ToString("D").Substring(0, 8); var subscriptionName = Guid.NewGuid().ToString("D").Substring(0, 8); var mgmtClient = new ServiceBusManagementClient(TestEnvironment.ServiceBusConnectionString); await using var sbClient = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); TopicDescription topicDescription = await mgmtClient.CreateTopicAsync(topicName); // Changing Last Updated Time topicDescription.AutoDeleteOnIdle = TimeSpan.FromMinutes(100); await mgmtClient.UpdateTopicAsync(topicDescription); SubscriptionDescription subscriptionDescription = await mgmtClient.CreateSubscriptionAsync(topicName, subscriptionName); // Changing Last Updated Time for subscription subscriptionDescription.AutoDeleteOnIdle = TimeSpan.FromMinutes(100); await mgmtClient.UpdateSubscriptionAsync(subscriptionDescription); // Populating 1 active message, 1 dead letter message and 1 scheduled message // Changing Last Accessed Time ServiceBusSender sender = sbClient.CreateSender(topicName); await sender.SendAsync(new ServiceBusMessage() { MessageId = "1" }); await sender.SendAsync(new ServiceBusMessage() { MessageId = "2" }); await sender.SendAsync(new ServiceBusMessage() { MessageId = "3", ScheduledEnqueueTime = DateTime.UtcNow.AddDays(1) }); ServiceBusReceiver receiver = sbClient.CreateReceiver(topicName, subscriptionName); ServiceBusReceivedMessage msg = await receiver.ReceiveAsync(); await receiver.DeadLetterAsync(msg.LockToken); List <SubscriptionRuntimeInfo> runtimeInfoList = new List <SubscriptionRuntimeInfo>(); await foreach (SubscriptionRuntimeInfo subscriptionRuntimeInfo in mgmtClient.GetSubscriptionsRuntimeInfoAsync(topicName)) { runtimeInfoList.Add(subscriptionRuntimeInfo); } runtimeInfoList = runtimeInfoList.Where(e => e.TopicName.StartsWith(nameof(GetSubscriptionRuntimeInfoTest).ToLower())).ToList(); Assert.True(runtimeInfoList.Count == 1, $"Expected 1 subscription but {runtimeInfoList.Count} subscriptions returned"); SubscriptionRuntimeInfo runtimeInfo = runtimeInfoList.First(); Assert.NotNull(runtimeInfo); Assert.AreEqual(topicName, runtimeInfo.TopicName); Assert.AreEqual(subscriptionName, runtimeInfo.SubscriptionName); Assert.True(runtimeInfo.CreatedAt < runtimeInfo.UpdatedAt); Assert.True(runtimeInfo.UpdatedAt < runtimeInfo.AccessedAt); Assert.AreEqual(1, runtimeInfo.CountDetails.ActiveMessageCount); Assert.AreEqual(1, runtimeInfo.CountDetails.DeadLetterMessageCount); Assert.AreEqual(0, runtimeInfo.CountDetails.ScheduledMessageCount); Assert.AreEqual(2, runtimeInfo.MessageCount); SubscriptionRuntimeInfo singleRuntimeInfo = await mgmtClient.GetSubscriptionRuntimeInfoAsync(topicName, subscriptionName); Assert.AreEqual(runtimeInfo.CreatedAt, singleRuntimeInfo.CreatedAt); Assert.AreEqual(runtimeInfo.AccessedAt, singleRuntimeInfo.AccessedAt); Assert.AreEqual(runtimeInfo.UpdatedAt, singleRuntimeInfo.UpdatedAt); Assert.AreEqual(runtimeInfo.SubscriptionName, singleRuntimeInfo.SubscriptionName); Assert.AreEqual(runtimeInfo.MessageCount, singleRuntimeInfo.MessageCount); Assert.AreEqual(runtimeInfo.CountDetails.ActiveMessageCount, singleRuntimeInfo.CountDetails.ActiveMessageCount); Assert.AreEqual(runtimeInfo.CountDetails.DeadLetterMessageCount, singleRuntimeInfo.CountDetails.DeadLetterMessageCount); Assert.AreEqual(runtimeInfo.CountDetails.ScheduledMessageCount, singleRuntimeInfo.CountDetails.ScheduledMessageCount); Assert.AreEqual(runtimeInfo.TopicName, singleRuntimeInfo.TopicName); await mgmtClient.DeleteTopicAsync(topicName); }