Example #1
0
        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);
                }
            }
        }
Example #2
0
        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.GetSender(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.SendBatchAsync(batch);

                var clientOptions = new ServiceBusReceiverOptions()
                {
                    ReceiveMode = ReceiveMode.ReceiveAndDelete
                };

                ServiceBusReceiver receiver = await client.GetSessionReceiverAsync(
                    scope.QueueName,
                    sessionId,
                    clientOptions);

                var receivedMessageCount = 0;
                var messageEnum          = messages.GetEnumerator();

                foreach (var item in await receiver.ReceiveBatchAsync(messageCount))
                {
                    messageEnum.MoveNext();
                    Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId);
                    Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId);
                    receivedMessageCount++;
                }
                Assert.AreEqual(messageCount, receivedMessageCount);

                var peekedMessage = receiver.PeekAsync();
                Assert.IsNull(peekedMessage.Result);
            }
        }
        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);
                }
            }
        }
Example #4
0
        static async Task SendMessageBatchAsync(string queueOrTopic)
        {
            // get the messages to be sent to the Service Bus queue
            var messages = CreateMessages();

            // total number of messages to be sent to the Service Bus queue
            var 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 SenderGet.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 SenderGet.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: {queueOrTopic}");
            }
        }
Example #5
0
        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.GetSender(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.CreateBatchAsync();

                    ServiceBusMessageBatch messageBatch = AddMessages(batch, messageCt, session);
                    await sender.SendBatchAsync(messageBatch);
                }

                // create receiver not scoped to a specific session
                for (int i = 0; i < 10; i++)
                {
                    ServiceBusReceiver receiver = await client.GetSessionReceiverAsync(scope.QueueName);

                    var session = receiver.GetSessionManager();
                    foreach (ServiceBusReceivedMessage peekedMessage in await receiver.PeekBatchAtAsync(
                                 sequenceNumber: 1,
                                 maxMessages: 10))
                    {
                        var sessionId = session.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();
                }
            }
        }
Example #6
0
        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 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.GetSender(scope.QueueName);
                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>();

                await sender.SendBatchAsync(batch);

                var receiver             = client.GetReceiver(scope.QueueName);
                var receivedMessageCount = 0;
                var messageEnum          = messages.GetEnumerator();

                foreach (var item in await receiver.ReceiveBatchAsync(messageCount))
                {
                    receivedMessageCount++;
                    messageEnum.MoveNext();
                    Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId);
                    await receiver.AbandonAsync(item);

                    Assert.AreEqual(item.DeliveryCount, 1);
                }
                Assert.AreEqual(messageCount, receivedMessageCount);

                messageEnum.Reset();
                receivedMessageCount = 0;
                foreach (var item in await receiver.PeekBatchAsync(messageCount))
                {
                    receivedMessageCount++;
                    messageEnum.MoveNext();
                    Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId);
                }
                Assert.AreEqual(messageCount, receivedMessageCount);
            }
        }
Example #8
0
        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 = AddMessages(batch, messageCount, sessionId).AsEnumerable <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.LockToken);
                    }
                }
                Assert.AreEqual(0, remainingMessages);

                var peekedMessage = receiver.PeekMessageAsync();
                Assert.IsNull(peekedMessage.Result);
            }
        }
        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 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.GetSender(scope.QueueName);
                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>();

                await sender.SendBatchAsync(batch);

                var          receiver             = client.GetReceiver(scope.QueueName);
                var          receivedMessageCount = 0;
                var          messageEnum          = messages.GetEnumerator();
                IList <long> sequenceNumbers      = new List <long>();

                foreach (var item in await receiver.ReceiveBatchAsync(messageCount))
                {
                    receivedMessageCount++;
                    messageEnum.MoveNext();
                    Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId);
                    sequenceNumbers.Add(item.SequenceNumber);
                    await receiver.DeferAsync(item);
                }
                Assert.AreEqual(messageCount, receivedMessageCount);

                IList <ServiceBusReceivedMessage> deferedMessages = await receiver.ReceiveDeferredMessageBatchAsync(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);
                }
            }
        }
Example #11
0
        public async Task LockSameSessionShouldThrow()
        {
            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);

                int messageCt = 10;
                var sessionId = Guid.NewGuid().ToString();
                // send the messages
                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                ServiceBusMessageBatch messageBatch = AddMessages(batch, messageCt, sessionId);

                await sender.SendBatchAsync(messageBatch);

                var options = new ServiceBusReceiverOptions
                {
                    RetryOptions = new ServiceBusRetryOptions
                    {
                        TryTimeout     = TimeSpan.FromSeconds(5),
                        MaximumRetries = 0
                    }
                };
                ServiceBusReceiver receiver1 = await client.GetSessionReceiverAsync(
                    scope.QueueName,
                    options,
                    sessionId);

                Assert.That(
                    async() =>
                    await client.GetSessionReceiverAsync(
                        scope.QueueName,
                        options,
                        sessionId),
                    Throws.Exception);
            }
        }
        protected async Task SeedMessagesAsync(int?messageCount = default)
        {
            Queue <ServiceBusMessage> messages = new();

            for (int i = 0; i < (messageCount ?? SeededMessageCount); i++)
            {
                var message = new ServiceBusMessage(MessageBody)
                {
                    SessionId = _useSessions ? Guid.NewGuid().ToString() : null
                };
                messages.Enqueue(message);
            }

            int startCount = messages.Count;

            while (messages.Any())
            {
                using ServiceBusMessageBatch messageBatch = await Sender.CreateMessageBatchAsync();

                if (messageBatch.TryAddMessage(messages.Peek()))
                {
                    messages.Dequeue();
                }
                else
                {
                    // if the first message can't fit, then it is too large for the batch
                    throw new InvalidOperationException($"Message {startCount - messages.Count} is too large and cannot be sent.");
                }

                // add as many messages as possible to the current batch
                while (messages.Any() && messageBatch.TryAddMessage(messages.Peek()))
                {
                    // dequeue the message from the .NET queue as it has been added to the batch
                    messages.Dequeue();
                }
                await Sender.SendMessagesAsync(messageBatch);
            }
        }
Example #13
0
        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 CanSendReceivedMessage()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
                var client = new ServiceBusClient(
                    TestEnvironment.FullyQualifiedNamespace,
                    GetTokenCredential());
                await using var sender             = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString).GetSender(scope.QueueName);
                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                var messageCt = 10;
                IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCt).AsEnumerable <ServiceBusMessage>();
                await sender.SendBatchAsync(batch);

                var receiver = client.GetReceiver(scope.QueueName, new ServiceBusReceiverOptions()
                {
                    ReceiveMode = ReceiveMode.PeekLock
                });
                var receivedMessages = await receiver.ReceiveBatchAsync(messageCt);

                foreach (ServiceBusReceivedMessage msg in receivedMessages)
                {
                    await sender.SendAsync(ServiceBusMessage.CreateFrom(msg));
                }

                int receivedMessageCount = 0;
                var messageEnum          = messages.GetEnumerator();

                foreach (var item in await receiver.ReceiveBatchAsync(messageCt))
                {
                    receivedMessageCount++;
                    messageEnum.MoveNext();
                    Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId);
                }
                Assert.AreEqual(messageCt, receivedMessages.Count);
            }
        }
Example #15
0
        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);
                }
            }
        }
Example #16
0
        public async Task ReceiveMessagesWhenQueueEmpty()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
                await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString, new ServiceBusClientOptions
                {
                    RetryOptions =
                    {
                        // very high TryTimeout
                        TryTimeout = TimeSpan.FromSeconds(120)
                    }
                });

                var messageCount        = 2;
                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);

                foreach (var message in await receiver.ReceiveMessagesAsync(2))
                {
                    await receiver.CompleteMessageAsync(message);
                }

                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)));
            }
        }
Example #17
0
        public async Task ReceiveMessagesInReceiveAndDeleteMode()
        {
            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.GetSender(scope.QueueName);
                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>();

                await sender.SendBatchAsync(batch);

                var clientOptions = new ServiceBusReceiverOptions()
                {
                    ReceiveMode = ReceiveMode.ReceiveAndDelete,
                };
                var receiver          = client.GetReceiver(scope.QueueName, clientOptions);
                var messageEnum       = messages.GetEnumerator();
                var remainingMessages = messageCount;
                while (remainingMessages > 0)
                {
                    foreach (var item in await receiver.ReceiveBatchAsync(remainingMessages).ConfigureAwait(false))
                    {
                        messageEnum.MoveNext();
                        Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId);
                        remainingMessages--;
                    }
                }
                Assert.AreEqual(0, remainingMessages);

                var peekedMessage = receiver.PeekAsync();
                Assert.IsNull(peekedMessage.Result);
            }
        }
Example #18
0
        public async Task DeadLetterMessagesSubscription(bool useSpecificSession)
        {
            await using (var scope = await ServiceBusScope.CreateWithTopic(enablePartitioning: false, enableSession: true))
            {
                await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
                ServiceBusSender sender = client.CreateSender(scope.TopicName);
                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 topicName        = scope.TopicName;
                var subscriptionName = scope.SubscriptionNames.First();

                var receiver = await client.AcceptSessionAsync(
                    topicName : topicName,
                    subscriptionName : subscriptionName,
                    useSpecificSession?sessionId : null);

                var remainingMessages = messageCount;
                var messageEnum       = messages.GetEnumerator();

                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);
                        var props = new Dictionary <string, object>();
                        // these should be ignored by DeadLetter property getters as they are not strings
                        props[AmqpMessageConstants.DeadLetterReasonHeader]           = DateTime.UtcNow;
                        props[AmqpMessageConstants.DeadLetterErrorDescriptionHeader] = DateTime.UtcNow;

                        await receiver.DeadLetterMessageAsync(item.LockToken, props);
                    }
                }
                Assert.AreEqual(0, remainingMessages);

                var peekedMessage = receiver.PeekMessageAsync();
                Assert.IsNull(peekedMessage.Result);

                messageEnum.Reset();
                remainingMessages = messageCount;
                var deadLetterReceiver = client.CreateReceiver(topicName, subscriptionName, new ServiceBusReceiverOptions
                {
                    SubQueue = SubQueue.DeadLetter
                });

                while (remainingMessages > 0)
                {
                    foreach (var msg in await deadLetterReceiver.ReceiveMessagesAsync(remainingMessages))
                    {
                        remainingMessages--;
                        messageEnum.MoveNext();
                        Assert.AreEqual(messageEnum.Current.MessageId, msg.MessageId);
                        Assert.AreEqual(messageEnum.Current.SessionId, msg.SessionId);
                        Assert.IsNull(msg.DeadLetterErrorDescription);
                        Assert.IsNull(msg.DeadLetterReason);
                        Assert.IsNotNull(msg.ApplicationProperties[AmqpMessageConstants.DeadLetterReasonHeader]);
                        Assert.IsNotNull(msg.ApplicationProperties[AmqpMessageConstants.DeadLetterErrorDescriptionHeader]);
                        await deadLetterReceiver.CompleteMessageAsync(msg.LockToken);
                    }
                }
                Assert.AreEqual(0, remainingMessages);

                var deadLetterMessage = await deadLetterReceiver.PeekMessageAsync();

                Assert.IsNull(deadLetterMessage);
            }
        }
        public async Task LogsSessionEvents()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true))
            {
                await using var client = CreateNoRetryClient();
                _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.FullyQualifiedNamespace));
                var messageCount = 10;

                ServiceBusSender sender = client.CreateSender(scope.QueueName);
                _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.FullyQualifiedNamespace) && e.Payload.Contains(sender.EntityPath));
                using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync();

                _listener.SingleEventById(ServiceBusEventSource.CreateMessageBatchStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CreateMessageBatchCompleteEvent, e => e.Payload.Contains(sender.Identifier));

                IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount, "sessionId").AsEnumerable <ServiceBusMessage>();

                await sender.SendMessagesAsync(batch);

                _listener.SingleEventById(ServiceBusEventSource.CreateSendLinkStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.RequestAuthorizationStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.RequestAuthorizationCompleteEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CreateSendLinkCompleteEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.SendMessageStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.SendMessageCompleteEvent, e => e.Payload.Contains(sender.Identifier));

                var receiver = client.CreateReceiver(scope.QueueName);
                _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace));

                // can't use a non-session receiver for session queue
                Assert.That(
                    async() => await receiver.ReceiveMessageAsync(),
                    Throws.InstanceOf <InvalidOperationException>());

                _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkStartEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkExceptionEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ReceiveMessageStartEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ReceiveMessageExceptionEvent, e => e.Payload.Contains(receiver.Identifier));

                var sessionReceiver = await client.AcceptNextSessionAsync(scope.QueueName);

                _listener.EventsById(ServiceBusEventSource.ClientCreateStartEvent).Where(e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace)).Any();
                _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkStartEvent, e => e.Payload.Contains(sessionReceiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkCompleteEvent, e => e.Payload.Contains(sessionReceiver.Identifier));

                var msg = await sessionReceiver.ReceiveMessageAsync();

                _listener.SingleEventById(ServiceBusEventSource.ReceiveMessageStartEvent, e => e.Payload.Contains(sessionReceiver.Identifier));

                msg = await sessionReceiver.PeekMessageAsync();

                _listener.SingleEventById(ServiceBusEventSource.CreateManagementLinkStartEvent, e => e.Payload.Contains(sessionReceiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CreateManagementLinkCompleteEvent, e => e.Payload.Contains(sessionReceiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.PeekMessageStartEvent, e => e.Payload.Contains(sessionReceiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.PeekMessageCompleteEvent, e => e.Payload.Contains(sessionReceiver.Identifier));

                await receiver.DisposeAsync();

                _listener.SingleEventById(ServiceBusEventSource.ClientCloseStartEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ClientCloseCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(receiver.Identifier));

                await sessionReceiver.DisposeAsync();

                _listener.SingleEventById(ServiceBusEventSource.ClientCloseStartEvent, e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(sessionReceiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ClientCloseCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(sessionReceiver.Identifier));
                await Task.Delay(TimeSpan.FromSeconds(2));

                _listener.SingleEventById(ServiceBusEventSource.ReceiveLinkClosedEvent, e => e.Payload.Contains(sessionReceiver.Identifier) &&
                                          e.Payload.Contains(sessionReceiver.SessionId));

                await sender.DisposeAsync();

                _listener.SingleEventById(ServiceBusEventSource.ClientCloseStartEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ClientCloseCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.Identifier));

                await client.DisposeAsync();

                _listener.SingleEventById(ServiceBusEventSource.ClientCloseStartEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ClientCloseCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.Identifier));
            }
        }
Example #20
0
        public async Task ReceiveStopProcessing(int numThreads)
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(
                             enablePartitioning: false,
                             enableSession: false))
            {
                await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
                ServiceBusSender sender = client.GetSender(scope.QueueName);
                int numMessages         = 100;
                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                ServiceBusMessageBatch messageBatch = AddMessages(batch, numMessages);

                await sender.SendBatchAsync(messageBatch);

                var options = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = numThreads,
                    ReceiveMode        = ReceiveMode.ReceiveAndDelete
                };
                var processor          = client.GetProcessor(scope.QueueName, options);
                int messageProcessedCt = 0;

                // stop processing halfway through
                int stopAfterMessagesCt = numMessages / 2;

                TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                processor.ProcessMessageAsync += ProcessMessage;
                processor.ProcessErrorAsync   += ExceptionHandler;

                await processor.StartProcessingAsync();

                Task ProcessMessage(ProcessMessageEventArgs args)
                {
                    var currentCt = Interlocked.Increment(ref messageProcessedCt);

                    TestContext.Progress.WriteLine(currentCt);
                    if (currentCt == stopAfterMessagesCt)
                    {
                        // awaiting here would cause a deadlock
                        _ = processor.StopProcessingAsync();
                        tcs.SetResult(true);
                    }
                    return(Task.CompletedTask);
                }

                await tcs.Task;
                var receiver = client.GetReceiver(scope.QueueName, new ServiceBusReceiverOptions
                {
                    RetryOptions = new ServiceBusRetryOptions()
                    {
                        TryTimeout = TimeSpan.FromSeconds(5),
                    }
                });

                var receivedMessages = await receiver.ReceiveBatchAsync(numMessages);

                // can't assert on the exact amount processed due to threads that
                // are already in flight when calling StopProcessingAsync, but we can at least verify that there are remaining messages
                Assert.IsTrue(receivedMessages.Count > 0);
                Assert.IsTrue(messageProcessedCt < numMessages);
            }
        }
Example #21
0
 /// <summary>
 ///   Sends a set of messages to the associated Queue/Topic using a batched approach.
 /// </summary>
 ///
 /// <param name="messageBatch">The set of messages to send.</param>
 /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
 ///
 /// <returns>A task to be resolved on when the operation has completed.</returns>
 ///
 public abstract Task SendBatchAsync(
     ServiceBusMessageBatch messageBatch,
     CancellationToken cancellationToken);
Example #22
0
        public async Task ProcessSessionMessages()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true))
            {
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string queueName        = scope.QueueName;
                await using var client = GetClient();

                #region Snippet:ServiceBusProcessSessionMessages
                //@@ 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
                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);

                // get the options to use for configuring the processor
                var options = new ServiceBusSessionProcessorOptions
                {
                    // By default after the message handler returns, the processor will complete the message
                    // If I want more fine-grained control over settlement, I can set this to false.
                    AutoCompleteMessages = false,

                    // I can also allow for processing multiple sessions
                    MaxConcurrentSessions = 5,

                    // By default, there will be a single concurrent call per session. I can
                    // increase that here to enable parallel processing within each session.
                    MaxConcurrentCallsPerSession = 2
                };

                // create a session processor that we can use to process the messages
                ServiceBusSessionProcessor processor = client.CreateSessionProcessor(queueName, options);

                // since the message handler will run in a background thread, in order to prevent
                // this sample from terminating immediately, we can use a task completion source that
                // we complete from within the message handler.
                TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                int processedMessageCount       = 0;
                processor.ProcessMessageAsync += MessageHandler;
                processor.ProcessErrorAsync   += ErrorHandler;

                async Task MessageHandler(ProcessSessionMessageEventArgs args)
                {
                    var body = args.Message.Body.ToString();

                    // we can evaluate application logic and use that to determine how to settle the message.
                    await args.CompleteMessageAsync(args.Message);

                    // we can also set arbitrary session state using this receiver
                    // the state is specific to the session, and not any particular message
                    await args.SetSessionStateAsync(new BinaryData("some state"));

                    // Once we've received the last message, complete the
                    // task completion source.
                    if (Interlocked.Increment(ref processedMessageCount) == 2)
                    {
                        tcs.SetResult(true);
                    }
                }

                Task ErrorHandler(ProcessErrorEventArgs args)
                {
                    // the error source tells me at what point in the processing an error occurred
                    Console.WriteLine(args.ErrorSource);
                    // the fully qualified namespace is available
                    Console.WriteLine(args.FullyQualifiedNamespace);
                    // as well as the entity path
                    Console.WriteLine(args.EntityPath);
                    Console.WriteLine(args.Exception.ToString());
                    return(Task.CompletedTask);
                }

                await processor.StartProcessingAsync();

                // await our task completion source task so that the message handler will be invoked at least once.
                await tcs.Task;

                // stop processing once the task completion source was completed.
                await processor.StopProcessingAsync();

                #endregion
            }
        }
        public async Task SendAndReceiveMessageSafeBatch()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
#if SNIPPET
                string connectionString = "<connection_string>";
                string queueName        = "<queue_name>";
#else
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string queueName        = scope.QueueName;
#endif
                // 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);

                #region Snippet:ServiceBusSendAndReceiveSafeBatch
                // add the messages that we plan to send to a local queue
                Queue <ServiceBusMessage> messages = new Queue <ServiceBusMessage>();
                messages.Enqueue(new ServiceBusMessage("First message"));
                messages.Enqueue(new ServiceBusMessage("Second message"));
                messages.Enqueue(new ServiceBusMessage("Third message"));

                // create a message batch that we can send
                // 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
                }
                #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
                    string body = receivedMessage.Body.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 LogsEvents()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
                await using var client = CreateNoRetryClient();
                _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.FullyQualifiedNamespace));
                var messageCount = 10;

                ServiceBusSender sender = client.CreateSender(scope.QueueName);
                _listener.EventsById(ServiceBusEventSource.ClientCreateStartEvent).Where(e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.FullyQualifiedNamespace) && e.Payload.Contains(sender.EntityPath));
                using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync();

                _listener.SingleEventById(ServiceBusEventSource.CreateMessageBatchStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CreateMessageBatchCompleteEvent, e => e.Payload.Contains(sender.Identifier));

                IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>();

                await sender.SendMessagesAsync(batch);

                _listener.SingleEventById(ServiceBusEventSource.CreateSendLinkStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.RequestAuthorizationStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.RequestAuthorizationCompleteEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CreateSendLinkCompleteEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.SendMessageStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.SendMessageCompleteEvent, e => e.Payload.Contains(sender.Identifier));

                Assert.That(
                    async() => await client.AcceptNextSessionAsync(scope.QueueName),
                    Throws.InstanceOf <InvalidOperationException>());
                _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace) && e.Payload.Contains(scope.QueueName));
                _listener.SingleEventById(ServiceBusEventSource.ClientCreateExceptionEvent, e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace) && e.Payload.Contains(scope.QueueName));

                var receiver = client.CreateReceiver(scope.QueueName);
                _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace));

                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);
                    }
                }
                _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkStartEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.RequestAuthorizationStartEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.RequestAuthorizationCompleteEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkCompleteEvent, e => e.Payload.Contains(receiver.Identifier));
                Assert.IsTrue(_listener.EventsById(ServiceBusEventSource.ReceiveMessageStartEvent).Any());
                Assert.IsTrue(_listener.EventsById(ServiceBusEventSource.ReceiveMessageCompleteEvent).Any());
                Assert.AreEqual(0, remainingMessages);
                messageEnum.Reset();

                foreach (var item in await receiver.PeekMessagesAsync(messageCount))
                {
                    messageEnum.MoveNext();
                    Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId);
                }

                _listener.SingleEventById(ServiceBusEventSource.CreateManagementLinkStartEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CreateManagementLinkCompleteEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.PeekMessageStartEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.PeekMessageCompleteEvent, e => e.Payload.Contains(receiver.Identifier));

                var seq = await sender.ScheduleMessageAsync(new ServiceBusMessage(), DateTimeOffset.UtcNow.AddMinutes(1));

                _listener.SingleEventById(ServiceBusEventSource.ScheduleMessageStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ScheduleMessageCompleteEvent, e => e.Payload.Contains(sender.Identifier));

                await sender.CancelScheduledMessageAsync(seq);

                _listener.SingleEventById(ServiceBusEventSource.CancelScheduledMessageStartEvent, e => e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.CancelScheduledMessageCompleteEvent, e => e.Payload.Contains(sender.Identifier));

                await receiver.DisposeAsync();

                _listener.SingleEventById(ServiceBusEventSource.ClientCloseStartEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ClientCloseCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(receiver.Identifier));
                // link closed event is fired asynchronously, so add a small delay
                await Task.Delay(TimeSpan.FromSeconds(5));

                _listener.SingleEventById(ServiceBusEventSource.ReceiveLinkClosedEvent, e => e.Payload.Contains(receiver.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ManagementLinkClosedEvent, e => e.Payload.Contains(receiver.Identifier));

                Assert.IsFalse(_listener.EventsById(ServiceBusEventSource.MaxMessagesExceedsPrefetchEvent).Any());
                receiver = client.CreateReceiver(scope.QueueName, new ServiceBusReceiverOptions {
                    PrefetchCount = 10
                });
                await receiver.ReceiveMessagesAsync(20, TimeSpan.FromSeconds(1));

                _listener.SingleEventById(ServiceBusEventSource.MaxMessagesExceedsPrefetchEvent, e => e.Payload.Contains(receiver.Identifier));

                await sender.DisposeAsync();

                _listener.SingleEventById(ServiceBusEventSource.ClientCloseStartEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ClientCloseCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.Identifier));

                await client.DisposeAsync();

                _listener.SingleEventById(ServiceBusEventSource.ClientCloseStartEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.Identifier));
                _listener.SingleEventById(ServiceBusEventSource.ClientCloseCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.Identifier));
            }
        }
        public async Task DeadLetterMessages(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();

                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.DeadLetterMessageAsync(item.LockToken, "testReason", "testDescription");
                    }
                }
                Assert.AreEqual(0, remainingMessages);

                var peekedMessage = receiver.PeekMessageAsync();
                Assert.IsNull(peekedMessage.Result);

                messageEnum.Reset();
                remainingMessages = messageCount;
                var deadLetterReceiver = client.CreateReceiver(scope.QueueName, new ServiceBusReceiverOptions
                {
                    SubQueue = SubQueue.DeadLetter
                });

                while (remainingMessages > 0)
                {
                    foreach (var msg in await deadLetterReceiver.ReceiveMessagesAsync(remainingMessages))
                    {
                        remainingMessages--;
                        messageEnum.MoveNext();
                        Assert.AreEqual(messageEnum.Current.MessageId, msg.MessageId);
                        Assert.AreEqual(messageEnum.Current.SessionId, msg.SessionId);
                        Assert.AreEqual("testReason", msg.DeadLetterReason);
                        Assert.AreEqual("testDescription", msg.DeadLetterErrorDescription);
                        await deadLetterReceiver.CompleteMessageAsync(msg.LockToken);
                    }
                }
                Assert.AreEqual(0, remainingMessages);

                var deadLetterMessage = await deadLetterReceiver.PeekMessageAsync();

                Assert.IsNull(deadLetterMessage);
            }
        }
        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);
            }
        }
Example #28
0
        public async Task ProcessMessages()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string queueName        = scope.QueueName;
                await using var client = GetClient();

                #region Snippet:ServiceBusProcessMessages
                //@@ 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);

                // get the sender
                ServiceBusSender sender = client.GetSender(queueName);

                // create a message batch that we can send
                ServiceBusMessageBatch messageBatch = await sender.CreateBatchAsync();

                messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("First")));
                messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second")));

                // send the message batch
                await sender.SendBatchAsync(messageBatch);

                // get the options to use for configuring the processor
                var options = new ServiceBusProcessorOptions
                {
                    // By default after the message handler returns, the processor will complete the message
                    // If I want more fine-grained control over settlement, I can set this to false.
                    AutoComplete = false,

                    // I can also allow for multi-threading
                    MaxConcurrentCalls = 2
                };

                // get a processor that we can use to process the messages
                ServiceBusProcessor processor = client.GetProcessor(queueName, options);

                // since the message handler will run in a background thread, in order to prevent
                // this sample from terminating immediately, we can use a task completion source that
                // we complete from within the message handler.
                TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                processor.ProcessMessageAsync += MessageHandler;
                processor.ProcessErrorAsync   += ErrorHandler;

                async Task MessageHandler(ProcessMessageEventArgs args)
                {
                    string body = Encoding.Default.GetString(args.Message.Body.ToArray());

                    Console.WriteLine(body);

                    // we can evaluate application logic and use that to determine how to settle the message.
                    await args.CompleteAsync(args.Message);

                    tcs.SetResult(true);
                }

                Task ErrorHandler(ProcessErrorEventArgs args)
                {
                    // the error source tells me at what point in the processing an error occurred
                    Console.WriteLine(args.ErrorSource);
                    // the fully qualified namespace is available
                    Console.WriteLine(args.FullyQualifiedNamespace);
                    // as well as the entity path
                    Console.WriteLine(args.EntityPath);
                    Console.WriteLine(args.Exception.ToString());
                    return(Task.CompletedTask);
                }

                await processor.StartProcessingAsync();

                // await our task completion source task so that the message handler will be invoked at least once.
                await tcs.Task;

                // stop processing once the task completion source was completed.
                await processor.StopProcessingAsync();

                #endregion
            }
        }
        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());
            }
        }
Example #30
0
 /// <summary>
 ///   Retrieves the inner transport batch from an <see cref="ServiceBusMessageBatch" />
 ///   using its private accessors.
 /// </summary>
 ///
 /// <param name="batch">The batch to retrieve the inner transport batch from.</param>
 ///
 /// <returns>The inner transport batch.</returns>
 ///
 private static TransportMessageBatch GetInnerBatch(ServiceBusMessageBatch batch) =>
 (TransportMessageBatch)
 typeof(ServiceBusMessageBatch)
 .GetProperty("InnerBatch", BindingFlags.Instance | BindingFlags.NonPublic)
 .GetValue(batch);