public async Task CanSendAnEmptyBodyMessageBatch() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); batch.TryAddMessage(new ServiceBusMessage(Array.Empty <byte>())); await sender.SendMessagesAsync(batch); } }
public async Task CanSendAMessageBatch() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); ServiceBusMessageBatch messageBatch = ServiceBusTestUtilities.AddMessages(batch, 3); await sender.SendMessagesAsync(messageBatch); } }
public async Task SendServiceBusMessagesAsync(List <ServiceBusMessage> listServiceBusMessages) { try { ServiceBusMessageBatch messageBatch = await _serviceBusSender.CreateMessageBatchAsync(); int batchMessageCount = 0; foreach (ServiceBusMessage serviceBusMessage in listServiceBusMessages) { if (!messageBatch.TryAddMessage(serviceBusMessage)) { // if it is too large for the batch _log.LogError("$The message { i} is too large to fit in the batch."); throw new Exception($"The message {serviceBusMessage.Body} is too large to fit in the batch."); } batchMessageCount++; if (batchMessageCount >= batchMessageCountLimit) { // Use the producer client to send the batch of messages to the Service Bus queue await _serviceBusSender.SendMessagesAsync(messageBatch); Console.WriteLine($"A batch of {messageBatch.Count} messages has been published to the queue."); messageBatch.Dispose(); messageBatch = await _serviceBusSender.CreateMessageBatchAsync(); batchMessageCount = 0; } } await _serviceBusSender.SendMessagesAsync(messageBatch); messageBatch.Dispose(); Console.WriteLine($"A batch of {messageBatch.Count} messages has been published to the queue."); } catch (Exception ex) { _log.LogError("error occurred", ex); } }
public async Task CannotSendLargerThanMaximumSize() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); // Actual limit is set by the service; query it from the batch. ServiceBusMessage message = new ServiceBusMessage(new byte[batch.MaxSizeInBytes + 10]); Assert.That(async() => await sender.SendMessageAsync(message), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)).EqualTo(ServiceBusFailureReason.MessageSizeExceeded)); } }
public async Task AbandonMessages() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); var messageCount = 10; ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); var receiver = client.CreateReceiver(scope.QueueName); var messageEnum = messages.GetEnumerator(); var remainingMessages = messageCount; IList <ServiceBusReceivedMessage> receivedMessages = new List <ServiceBusReceivedMessage>(); while (remainingMessages > 0) { foreach (var msg in await receiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, msg.MessageId); receivedMessages.Add(msg); Assert.AreEqual(msg.DeliveryCount, 1); } } Assert.AreEqual(0, remainingMessages); // don't abandon in the receive loop // as this would make the message available to be immediately received again foreach (var msg in receivedMessages) { await receiver.AbandonMessageAsync(msg); } messageEnum.Reset(); var receivedMessageCount = 0; foreach (var item in await receiver.PeekMessagesAsync(messageCount)) { receivedMessageCount++; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); } Assert.AreEqual(messageCount, receivedMessageCount); } }
public async Task PeekSession(long?sequenceNumber) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: true, enableSession: true)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); var messageCt = 10; var sessionId = Guid.NewGuid().ToString(); // send the messages using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> sentMessages = AddMessages(batch, messageCt, sessionId, sessionId) .AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); Dictionary <string, ServiceBusMessage> sentMessageIdToMsg = new Dictionary <string, ServiceBusMessage>(); foreach (ServiceBusMessage message in sentMessages) { sentMessageIdToMsg.Add(message.MessageId, message); } var receiver = await client.AcceptSessionAsync( scope.QueueName, sessionId); sequenceNumber ??= 1; // verify peeked == send var ct = 0; foreach (ServiceBusReceivedMessage peekedMessage in await receiver.PeekMessagesAsync( messageCt, sequenceNumber)) { var peekedText = peekedMessage.Body.ToString(); var sentMsg = sentMessageIdToMsg[peekedMessage.MessageId]; sentMessageIdToMsg.Remove(peekedMessage.MessageId); Assert.AreEqual(sentMsg.Body.ToString(), peekedText); Assert.AreEqual(sentMsg.SessionId, peekedMessage.SessionId); Assert.IsTrue(peekedMessage.SequenceNumber >= sequenceNumber); ct++; } if (sequenceNumber == 1) { Assert.AreEqual(messageCt, ct); } } }
public async Task DeferMessages() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); var messageCount = 10; ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); var receiver = client.CreateReceiver(scope.QueueName); var messageEnum = messages.GetEnumerator(); IList <long> sequenceNumbers = new List <long>(); var remainingMessages = messageCount; while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); sequenceNumbers.Add(item.SequenceNumber); await receiver.DeferMessageAsync(item.LockToken); } } Assert.AreEqual(0, remainingMessages); IReadOnlyList <ServiceBusReceivedMessage> deferredMessages = await receiver.ReceiveDeferredMessagesAsync(sequenceNumbers); var messageList = messages.ToList(); Assert.AreEqual(messageList.Count, deferredMessages.Count); for (int i = 0; i < messageList.Count; i++) { Assert.AreEqual(messageList[i].MessageId, deferredMessages[i].MessageId); Assert.AreEqual(messageList[i].Body.ToBytes().ToArray(), deferredMessages[i].Body.ToBytes().ToArray()); } // verify that looking up a non-existent sequence number will throw sequenceNumbers.Add(45); Assert.That( async() => await receiver.ReceiveDeferredMessagesAsync(sequenceNumbers), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)).EqualTo(ServiceBusFailureReason.MessageNotFound)); } }
public async Task TryAddReturnsFalseIfSizeExceed() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); // Actual limit is 262144 bytes for a single message. Assert.That(() => batch.TryAddMessage(new ServiceBusMessage(new byte[200000])), Is.True, "A message was rejected by the batch; all messages should be accepted."); Assert.That(() => batch.TryAddMessage(new ServiceBusMessage(new byte[200000])), Is.False, "A message was rejected by the batch; message size exceed."); await sender.SendMessagesAsync(batch); } }
public async Task ReceiveFromSpecificSession() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { 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 batch that we can send ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync(); messageBatch.TryAddMessage( new ServiceBusMessage(Encoding.UTF8.GetBytes("First")) { SessionId = "Session1" }); messageBatch.TryAddMessage( new ServiceBusMessage(Encoding.UTF8.GetBytes("Second")) { SessionId = "Session2" }); // send the message batch await sender.SendMessagesAsync(messageBatch); #region Snippet:ServiceBusReceiveFromSpecificSession // create a receiver specifying a particular session ServiceBusSessionReceiver receiver = await client.CreateSessionReceiverAsync( queueName, new ServiceBusSessionReceiverOptions { SessionId = "Session2" }); // the received message is a different type as it contains some service set properties ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync(); Console.WriteLine(receivedMessage.SessionId); #endregion Assert.AreEqual(Encoding.UTF8.GetBytes("Second"), receivedMessage.Body.ToBytes().ToArray()); Assert.AreEqual("Session2", receivedMessage.SessionId); } }
static async Task SendMessageBatchAsync() { // create a Service Bus client await using (ServiceBusClient client = new ServiceBusClient(connectionString)) { // create a sender for the queue ServiceBusSender sender = client.CreateSender(queueName); // get the messages to be sent to the Service Bus queue Queue <ServiceBusMessage> messages = CreateMessages(); // total number of messages to be sent to the Service Bus queue int messageCount = messages.Count; // while all messages are not sent to the Service Bus queue while (messages.Count > 0) { // start a new batch using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync(); // add the first message to the batch if (messageBatch.TryAddMessage(messages.Peek())) { // dequeue the message from the .NET queue once the message is added to the batch messages.Dequeue(); } else { // if the first message can't fit, then it is too large for the batch throw new Exception($"Message {messageCount - messages.Count} is too large and cannot be sent."); } // add as many messages as possible to the current batch while (messages.Count > 0 && messageBatch.TryAddMessage(messages.Peek())) { // dequeue the message from the .NET queue as it has been added to the batch messages.Dequeue(); } // now, send the batch await sender.SendMessagesAsync(messageBatch); // if there are any remaining messages in the .NET queue, the while loop repeats } Console.WriteLine($"Sent a batch of {messageCount} messages to the topic: {queueName}"); } }
public async Task ReceiveMessagesWhenQueueEmpty() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString, new ServiceBusClientOptions { RetryOptions = { // very high TryTimeout TryTimeout = TimeSpan.FromSeconds(120) } }); var messageCount = 2; var sessionId = "sessionId1"; ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount, sessionId).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); ServiceBusReceiver receiver = await client.AcceptNextSessionAsync( scope.QueueName, new ServiceBusSessionReceiverOptions { PrefetchCount = 100 }); var remainingMessages = messageCount; while (remainingMessages > 0) { foreach (var message in await receiver.ReceiveMessagesAsync(remainingMessages)) { await receiver.CompleteMessageAsync(message); remainingMessages--; } } using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(3)); var start = DateTime.UtcNow; Assert.ThrowsAsync <TaskCanceledException>(async() => await receiver.ReceiveMessagesAsync(1, cancellationToken: cancellationTokenSource.Token)); var stop = DateTime.UtcNow; Assert.That(stop - start, Is.EqualTo(TimeSpan.FromSeconds(3)).Within(TimeSpan.FromSeconds(3))); } }
public async Task DeferMessages(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.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount, sessionId).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); var receiver = await client.CreateSessionReceiverAsync( scope.QueueName, new ServiceBusSessionReceiverOptions { SessionId = useSpecificSession ? sessionId : null }); var remainingMessages = messageCount; var messageEnum = messages.GetEnumerator(); IList <long> sequenceNumbers = new List <long>(); while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId); sequenceNumbers.Add(item.SequenceNumber); await receiver.DeferMessageAsync(item.LockToken); } } Assert.AreEqual(0, remainingMessages); IReadOnlyList <ServiceBusReceivedMessage> deferedMessages = await receiver.ReceiveDeferredMessagesAsync(sequenceNumbers); var messageList = messages.ToList(); Assert.AreEqual(messageList.Count, deferedMessages.Count); for (int i = 0; i < messageList.Count; i++) { Assert.AreEqual(messageList[i].MessageId, deferedMessages[i].MessageId); } } }
public async Task DeferMessagesArray() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); var messageCount = 10; ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); var receiver = client.CreateReceiver(scope.QueueName); var messageEnum = messages.GetEnumerator(); long[] sequenceNumbers = new long[messageCount]; var remainingMessages = messageCount; int idx = 0; while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); sequenceNumbers[idx++] = item.SequenceNumber; await receiver.DeferMessageAsync(item.LockToken); } } Assert.AreEqual(0, remainingMessages); IReadOnlyList <ServiceBusReceivedMessage> deferredMessages = await receiver.ReceiveDeferredMessagesAsync(sequenceNumbers); var messageList = messages.ToList(); Assert.AreEqual(messageList.Count, deferredMessages.Count); for (int i = 0; i < messageList.Count; i++) { Assert.AreEqual(messageList[i].MessageId, deferredMessages[i].MessageId); Assert.AreEqual(messageList[i].Body.ToArray(), deferredMessages[i].Body.ToArray()); } // verify that an empty array can be passed deferredMessages = await receiver.ReceiveDeferredMessagesAsync(Array.Empty <long>()); Assert.IsEmpty(deferredMessages); } }
public async Task CancellingDoesNotLoseMessages(bool prefetch) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = CreateClient(); var messageCount = 10; ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); var receiver = client.CreateReceiver( scope.QueueName, new ServiceBusReceiverOptions { ReceiveMode = ServiceBusReceiveMode.ReceiveAndDelete, PrefetchCount = prefetch ? 10 : 0 }); using var cancellationTokenSource = new CancellationTokenSource(500); var received = 0; try { for (int i = 0; i < messageCount; i++) { await receiver.ReceiveMessageAsync(cancellationToken : cancellationTokenSource.Token); received++; await Task.Delay(100); } } catch (TaskCanceledException) { } Assert.Less(received, messageCount); var remaining = messageCount - received; for (int i = 0; i < remaining; i++) { await receiver.ReceiveMessageAsync(); received++; } Assert.AreEqual(messageCount, received); } }
public async Task CanSendLargeMessageBatch() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); // Actual limit is 262144 bytes for a single message. batch.TryAddMessage(new ServiceBusMessage(new byte[100000 / 3])); batch.TryAddMessage(new ServiceBusMessage(new byte[100000 / 3])); batch.TryAddMessage(new ServiceBusMessage(new byte[100000 / 3])); await sender.SendMessagesAsync(batch); } }
public async Task SendAndReceiveMessageSafeBatch() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; //@@ 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 batch that we can send #region Snippet:ServiceBusSendAndReceiveSafeBatch ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync(); messageBatch.TryAddMessage(new ServiceBusMessage(Encoding.UTF8.GetBytes("First"))); messageBatch.TryAddMessage(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second"))); // send the message batch await sender.SendMessagesAsync(messageBatch); #endregion // create a receiver that we can use to receive the messages ServiceBusReceiver receiver = client.CreateReceiver(queueName); // the received message is a different type as it contains some service set properties IReadOnlyList <ServiceBusReceivedMessage> receivedMessages = await receiver.ReceiveMessagesAsync(maxMessages : 2); foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages) { // get the message body as a string using an implicit cast string body = receivedMessage.Body.ToString(); } var sentMessagesEnum = messageBatch.AsEnumerable <ServiceBusMessage>().GetEnumerator(); foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages) { sentMessagesEnum.MoveNext(); Assert.AreEqual(sentMessagesEnum.Current.Body.ToString(), receivedMessage.Body.ToString()); } } }
public async Task ReceiveMessagesInReceiveAndDeleteMode() { 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.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount, sessionId).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); var clientOptions = new ServiceBusSessionReceiverOptions { ReceiveMode = ServiceBusReceiveMode.ReceiveAndDelete }; ServiceBusReceiver receiver = await client.AcceptSessionAsync( scope.QueueName, sessionId, clientOptions); var remainingMessages = messageCount; var messageEnum = messages.GetEnumerator(); while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveMessagesAsync(remainingMessages)) { messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId); remainingMessages--; } } Assert.AreEqual(0, remainingMessages); var peekedMessage = receiver.PeekMessageAsync(); Assert.IsNull(peekedMessage.Result); } }
public async Task TryAddReturnsFalseIfSizeExceed() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); // Actual limit is set by the service; query it from the batch. Because this will be used for the // message body, leave some padding for the conversion and batch envelope. var padding = 500; var size = (batch.MaxSizeInBytes - padding); Assert.That(() => batch.TryAddMessage(new ServiceBusMessage(new byte[size])), Is.True, "A message was rejected by the batch; all messages should be accepted."); Assert.That(() => batch.TryAddMessage(new ServiceBusMessage(new byte[padding + 1])), Is.False, "A message was rejected by the batch; message size exceed."); await sender.SendMessagesAsync(batch); } }
public async Task CanSendLargeMessageBatch() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); // Actual limit is set by the service; query it from the batch. Because this will be used for the // message body, leave some padding for the conversion and batch envelope. var size = (long)(Math.Floor(batch.MaxSizeInBytes / 3.0f) - 150); batch.TryAddMessage(new ServiceBusMessage(new byte[size])); batch.TryAddMessage(new ServiceBusMessage(new byte[size])); batch.TryAddMessage(new ServiceBusMessage(new byte[size])); await sender.SendMessagesAsync(batch); } }
static async Task Main() { // The Service Bus client types are safe to cache and use as a singleton for the lifetime // of the application, which is best practice when messages are being published or read // regularly. // // Create the clients that we'll use for sending and processing messages. client = new ServiceBusClient(connectionString); sender = client.CreateSender(queueName); // create a batch using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync(); for (int i = 1; i <= numOfMessages; i++) { // try adding a message to the batch if (!messageBatch.TryAddMessage(new ServiceBusMessage($"Message {i} Data"))) { // if it is too large for the batch throw new Exception($"The message {i} is too large to fit in the batch."); } } try { // Use the producer client to send the batch of messages to the Service Bus queue await sender.SendMessagesAsync(messageBatch); Console.WriteLine($"A batch of {numOfMessages} messages has been published to the queue."); } finally { // Calling DisposeAsync on client types is required to ensure that network // resources and other unmanaged objects are properly cleaned up. await sender.DisposeAsync(); await client.DisposeAsync(); } Console.WriteLine("Press any key to end the application"); Console.ReadKey(); }
public async Task ReceiveMessagesInPeekLockMode() { 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.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount, sessionId).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); ServiceBusReceiver receiver = await client.AcceptNextSessionAsync( scope.QueueName, new ServiceBusSessionReceiverOptions { PrefetchCount = 100 }); var messageEnum = messages.GetEnumerator(); foreach (var item in await receiver.ReceiveMessagesAsync(messageCount)) { messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId); Assert.AreEqual(item.DeliveryCount, 1); } messageEnum.Reset(); foreach (var item in await receiver.PeekMessagesAsync(messageCount)) { messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId); } } }
public async Task CanSendLargeMessageBatch() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: true, enableSession: true)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); await AddAndSendMessages(); batch.Clear(); Assert.AreEqual(0, batch.Count); Assert.AreEqual(0, batch.SizeInBytes); await AddAndSendMessages(); async Task AddAndSendMessages() { // service limits to 4500 messages but we have not added this to our client validation yet while (batch.Count < 4500 && batch.TryAddMessage( new ServiceBusMessage(new byte[50]) { MessageId = "new message ID that takes up some space", SessionId = "sessionId", PartitionKey = "sessionId", ApplicationProperties = { { "key", "value" } } })) { } if (batch.Count < 4500) { // the difference in size from the max allowable size should be less than the size of 1 message Assert.IsTrue(batch.MaxSizeInBytes - batch.SizeInBytes < 180); } Assert.Greater(batch.Count, 0); await sender.SendMessagesAsync(batch); } } }
public static async Task SendMessageSafeBatchAsync(string connectionString, string queueName, List <string> messageTexts) { await using var client = new ServiceBusClient(connectionString); // create the sender ServiceBusSender sender = client.CreateSender(queueName); // create a message that we can send. UTF-8 encoding is used when providing a string. Queue <ServiceBusMessage> messages = new Queue <ServiceBusMessage>(); messageTexts.ForEach(msg => messages.Enqueue(new ServiceBusMessage(msg))); while (messages.Count > 0) { // start a new batch using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync(); // add the first message to the batch if (messageBatch.TryAddMessage(messages.Peek())) { // dequeue the message from the .NET queue once the message is added to the batch messages.Dequeue(); } else { // if the first message can't fit, then it is too large for the batch throw new Exception($"Message {messageTexts.Count - messages.Count} is too large and cannot be sent."); } // add as many messages as possible to the current batch while (messages.Count > 0 && messageBatch.TryAddMessage(messages.Peek())) { // dequeue the message from the .NET queue as it has been added to the batch messages.Dequeue(); } // now, send the batch await sender.SendMessagesAsync(messageBatch); } }
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.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = ServiceBusTestUtilities.AddMessages(batch, messageCount, sessionId).AsReadOnly <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); ServiceBusReceiver receiver = await client.AcceptSessionAsync( scope.QueueName, useSpecificSession?sessionId : null); var messageEnum = messages.GetEnumerator(); var remainingMessages = messageCount; while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId); await receiver.CompleteMessageAsync(item); } } Assert.AreEqual(0, remainingMessages); var peekedMessage = receiver.PeekMessageAsync(); Assert.IsNull(peekedMessage.Result); } }
public async Task RoundRobinSessions() { 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 messageCt = 10; HashSet <string> sessions = new HashSet <string>() { "1", "2", "3" }; // send the messages foreach (string session in sessions) { using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); ServiceBusMessageBatch messageBatch = AddMessages(batch, messageCt, session); await sender.SendMessagesAsync(messageBatch); } // create receiver not scoped to a specific session for (int i = 0; i < 10; i++) { ServiceBusSessionReceiver receiver = await client.AcceptNextSessionAsync(scope.QueueName); foreach (ServiceBusReceivedMessage peekedMessage in await receiver.PeekMessagesAsync( fromSequenceNumber: 1, maxMessages: 10)) { var sessionId = receiver.SessionId; Assert.AreEqual(sessionId, peekedMessage.SessionId); } // Close the receiver client when we are done with it. Since the sessionClient doesn't own the underlying connection, the connection remains open, but the session link will be closed. await receiver.DisposeAsync(); } } }
public async Task SendBatchMessages() { //RECUPERAMOS LOS MENSAJES EN EL BATCH Queue <ServiceBusMessage> colamensajes = this.CreateMessages(); ServiceBusSender sender = this.client.CreateSender("programeitors"); //LOS MENSAJES ESTAN EN MODO ENQUEUE A MEDIDA QUE LOS VAYAMOS PROCESANDO SE IRAN QUITANDO DE LA COLA Y PASANDO+ // A PROCESO DEQUEUE, NO SABEMOS CUANTO TARDARÁ ESTE PROCESO, DEBEMOS HACER EL PROCESO DE BATCH EN UN BUCLE //MIENTRAS LOS MENSAJES ESTEN EN LA COLA while (colamensajes.Count > 0) { //TODOS LOS MENSAJES DE LA COLA SE PROCESAN CON BATCH ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); //LOS MENSAJES SE AGREGAN AL BATCH Y SE VAN PROCESANDO if (batch.TryAddMessage(colamensajes.Peek())) { colamensajes.Dequeue(); } //SE VAN ENVIANDO LOS BATCH await sender.SendMessagesAsync(batch); } }
public async Task ReceiveMessagesInPeekLockMode() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); var messageCount = 10; ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); var receiver = client.CreateReceiver(scope.QueueName); var messageEnum = messages.GetEnumerator(); var remainingMessages = messageCount; while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(item.DeliveryCount, 1); } } Assert.AreEqual(0, remainingMessages); messageEnum.Reset(); foreach (var item in await receiver.PeekMessagesAsync(messageCount)) { messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); } } }
public async Task UserSettlingWithAutoCompleteDoesNotThrow(int numThreads) { await using (var scope = await ServiceBusScope.CreateWithQueue( enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); // use double the number of threads so we can make sure we test that we don't // retrieve more messages than expected when there are more messages available using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); var messageSendCt = numThreads * 2; ServiceBusMessageBatch messageBatch = AddMessages(batch, messageSendCt); await sender.SendMessagesAsync(messageBatch); var options = new ServiceBusProcessorOptions { MaxConcurrentCalls = numThreads, AutoComplete = true, MaxReceiveWaitTime = TimeSpan.FromSeconds(30) }; var processor = client.CreateProcessor(scope.QueueName, options); int messageCt = 0; TaskCompletionSource <bool>[] completionSources = Enumerable .Range(0, numThreads) .Select(index => new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously)) .ToArray(); var completionSourceIndex = -1; processor.ProcessMessageAsync += ProcessMessage; processor.ProcessErrorAsync += ExceptionHandler; await processor.StartProcessingAsync(); async Task ProcessMessage(ProcessMessageEventArgs args) { try { var message = args.Message; switch (numThreads) { case 1: await args.CompleteMessageAsync(message, args.CancellationToken); break; case 5: await args.AbandonMessageAsync(message); break; case 10: await args.DeadLetterMessageAsync(message); break; case 20: await args.DeferMessageAsync(message); break; } Interlocked.Increment(ref messageCt); } finally { var setIndex = Interlocked.Increment(ref completionSourceIndex); if (setIndex < numThreads) { completionSources[setIndex].SetResult(true); } } } await Task.WhenAll(completionSources.Select(source => source.Task)); await processor.StopProcessingAsync(); // we complete each task after one message being processed, so the total number of messages // processed should equal the number of threads, but it's possible that we may process a few more per thread. Assert.IsTrue(messageCt >= numThreads); Assert.IsTrue(messageCt <= messageSendCt, messageCt.ToString()); } }
public async Task MaxAutoLockRenewalDurationRespected(int numThreads, int autoLockRenewalDuration) { var lockDuration = TimeSpan.FromSeconds(5); await using (var scope = await ServiceBusScope.CreateWithQueue( enablePartitioning: false, enableSession: false, lockDuration: lockDuration)) { await using var client = GetClient(); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); var messageSendCt = numThreads; ServiceBusMessageBatch messageBatch = AddMessages(batch, messageSendCt); await sender.SendMessagesAsync(messageBatch); var options = new ServiceBusProcessorOptions { MaxConcurrentCalls = numThreads, AutoComplete = false, MaxAutoLockRenewalDuration = TimeSpan.FromSeconds(autoLockRenewalDuration) }; var processor = client.CreateProcessor(scope.QueueName, options); int messageCt = 0; TaskCompletionSource <bool>[] completionSources = Enumerable .Range(0, numThreads) .Select(index => new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously)) .ToArray(); var completionSourceIndex = -1; processor.ProcessMessageAsync += ProcessMessage; processor.ProcessErrorAsync += ExceptionHandler; await processor.StartProcessingAsync(); async Task ProcessMessage(ProcessMessageEventArgs args) { var message = args.Message; // wait 2x lock duration in case the // lock was renewed already await Task.Delay(lockDuration.Add(lockDuration)); var lockedUntil = message.LockedUntil; if (!args.CancellationToken.IsCancellationRequested) { // only do the assertion if cancellation wasn't requested as otherwise // the exception we would get is a TaskCanceledException rather than ServiceBusException Assert.AreEqual(lockedUntil, message.LockedUntil); Assert.That( async() => await args.CompleteMessageAsync(message, args.CancellationToken), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)).EqualTo(ServiceBusException.FailureReason.MessageLockLost)); Interlocked.Increment(ref messageCt); var setIndex = Interlocked.Increment(ref completionSourceIndex); completionSources[setIndex].SetResult(true); } } await Task.WhenAll(completionSources.Select(source => source.Task)); await processor.StopProcessingAsync(); Assert.AreEqual(numThreads, messageCt); } }
public async Task AutoLockRenewalWorks(int numThreads) { var lockDuration = TimeSpan.FromSeconds(10); await using (var scope = await ServiceBusScope.CreateWithQueue( enablePartitioning: false, enableSession: false, lockDuration: lockDuration)) { await using var client = GetClient(); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); var messageSendCt = numThreads; ServiceBusMessageBatch messageBatch = AddMessages(batch, messageSendCt); await sender.SendMessagesAsync(messageBatch); var options = new ServiceBusProcessorOptions { MaxConcurrentCalls = numThreads, AutoComplete = false }; var processor = client.CreateProcessor(scope.QueueName, options); int messageCt = 0; TaskCompletionSource <bool>[] completionSources = Enumerable .Range(0, numThreads) .Select(index => new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously)) .ToArray(); var completionSourceIndex = -1; processor.ProcessMessageAsync += ProcessMessage; processor.ProcessErrorAsync += args => { // If the connection drops due to network flakiness // after the message is received but before we // complete it, we will get a message lock // lost exception. We are still able to verify // that the message will be completed eventually. var exception = (ServiceBusException)args.Exception; if (!(args.Exception is ServiceBusException sbEx) || sbEx.Reason != ServiceBusException.FailureReason.MessageLockLost) { Assert.Fail(args.Exception.ToString()); } return(Task.CompletedTask); }; await processor.StartProcessingAsync(); async Task ProcessMessage(ProcessMessageEventArgs args) { var message = args.Message; var lockedUntil = message.LockedUntil; await Task.Delay(lockDuration); await args.CompleteMessageAsync(message, args.CancellationToken); Interlocked.Increment(ref messageCt); var setIndex = Interlocked.Increment(ref completionSourceIndex); completionSources[setIndex].SetResult(true); } await Task.WhenAll(completionSources.Select(source => source.Task)); Assert.IsTrue(processor.IsProcessing); await processor.StopProcessingAsync(); Assert.IsFalse(processor.IsProcessing); Assert.AreEqual(numThreads, messageCt); } }