public async Task SessionProcessorActivities()
        {
            ClientDiagnosticListener.ProducedLink[] messageActivities = null;
            int  messageProcessedCt = 0;
            bool callbackExecuted   = false;

            _listener = new ClientDiagnosticListener(
                EntityScopeFactory.DiagnosticNamespace,
                scopeStartCallback: scope =>
            {
                if (scope.Name == DiagnosticProperty.ProcessSessionMessageActivityName)
                {
                    Assert.IsNotNull(messageActivities);
                    Assert.AreEqual(
                        messageActivities[messageProcessedCt],
                        scope.Links.Single());
                    callbackExecuted = true;
                }
            });
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true))
            {
                var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
                ServiceBusSender sender = client.CreateSender(scope.QueueName);
                var messageCt           = 2;
                var msgs = ServiceBusTestUtilities.GetMessages(messageCt, "sessionId");
                await sender.SendMessagesAsync(msgs);

                Activity[] sendActivities = AssertSendActivities(false, sender, msgs);
                messageActivities = sendActivities.Select(a => new ClientDiagnosticListener.ProducedLink(a.ParentId, a.TraceStateString)).ToArray();

                ServiceBusSessionProcessor processor = client.CreateSessionProcessor(scope.QueueName,
                                                                                     new ServiceBusSessionProcessorOptions
                {
                    AutoCompleteMessages  = false,
                    SessionIdleTimeout    = TimeSpan.FromSeconds(10),
                    MaxConcurrentSessions = 1
                });
                TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>();
                processor.ProcessMessageAsync += args =>
                {
                    if (++messageProcessedCt == messageCt)
                    {
                        tcs.SetResult(true);
                    }
                    return(Task.CompletedTask);
                };
                processor.ProcessErrorAsync += ServiceBusTestUtilities.ExceptionHandler;
                await processor.StartProcessingAsync();

                await tcs.Task;
                await processor.StopProcessingAsync();

                for (int i = 0; i < messageCt; i++)
                {
                    _listener.AssertAndRemoveScope(DiagnosticProperty.ReceiveActivityName);
                    var processScope = _listener.AssertAndRemoveScope(DiagnosticProperty.ProcessSessionMessageActivityName);
                    AssertCommonTags(processScope.Activity, processor.EntityPath, processor.FullyQualifiedNamespace);
                }
                Assert.IsTrue(callbackExecuted);
            }
        }
Ejemplo n.º 2
0
        public async Task LogsSessionEvents()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true))
            {
                await using var client = GetNoRetryClient();
                _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));
            }
        }
Ejemplo n.º 3
0
        public async Task UserSettlingWithAutoCompleteDoesNotThrow(int numThreads)
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(
                             enablePartitioning: false,
                             enableSession: false))
            {
                await using var client = CreateClient();
                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,
                    AutoCompleteMessages = true,
                    MaxReceiveWaitTime   = TimeSpan.FromSeconds(30)
                };
                await using 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 TransactionThrowsWhenOperationsOfDifferentPartitionsAreInSameTransaction()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: true, enableSession: false))
            {
                await using var client = CreateClient();
                ServiceBusSender   sender   = client.CreateSender(scope.QueueName);
                ServiceBusReceiver receiver = client.CreateReceiver(scope.QueueName);

                string            body     = Guid.NewGuid().ToString("N");
                ServiceBusMessage message1 = GetMessage(partitionKey: "1");
                ServiceBusMessage message2 = GetMessage(partitionKey: "2");

                // Two send operations to different partitions.
                var transaction = new CommittableTransaction();
                using (TransactionScope ts = new TransactionScope(transaction, TransactionScopeAsyncFlowOption.Enabled))
                {
                    await sender.SendMessageAsync(message1);

                    Assert.ThrowsAsync <InvalidOperationException>(
                        async() => await sender.SendMessageAsync(message2));
                    ts.Complete();
                }

                transaction.Rollback();

                // Adding delay since transaction Commit/Rollback is an asynchronous operation.
                // Operating on the same message should not be done.
                await Task.Delay(TimeSpan.FromSeconds(2));

                // Two complete operations to different partitions.
                await sender.SendMessageAsync(message1);

                await sender.SendMessageAsync(message2);

                ServiceBusReceivedMessage receivedMessage1 = await receiver.ReceiveMessageAsync();

                Assert.NotNull(receivedMessage1);
                ServiceBusReceivedMessage receivedMessage2 = await receiver.ReceiveMessageAsync();

                Assert.NotNull(receivedMessage2);

                transaction = new CommittableTransaction();
                using (TransactionScope ts = new TransactionScope(transaction, TransactionScopeAsyncFlowOption.Enabled))
                {
                    await receiver.CompleteMessageAsync(receivedMessage1);

                    Assert.ThrowsAsync <InvalidOperationException>(
                        async() => await receiver.CompleteMessageAsync(receivedMessage2));
                    ts.Complete();
                }

                transaction.Rollback();

                // Adding delay since transaction Commit/Rollback is an asynchronous operation.
                // Operating on the same message should not be done.
                await Task.Delay(TimeSpan.FromSeconds(2));

                await receiver.CompleteMessageAsync(receivedMessage1);

                // the service seems to abandon the message that
                // triggered the InvalidOperationException
                // in the transaction
                Assert.That(
                    async() =>
                    await receiver.CompleteMessageAsync(receivedMessage2), Throws.InstanceOf <ServiceBusException>()
                    .And.Property(nameof(ServiceBusException.Reason))
                    .EqualTo(ServiceBusFailureReason.MessageLockLost));
            }
        }
Ejemplo n.º 5
0
        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.CreateBatchAsync();

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

                await sender.SendBatchAsync(batch);

                var receiver = await client.CreateSessionReceiverAsync(
                    scope.QueueName,
                    sessionId : useSpecificSession?sessionId : null);

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

                while (remainingMessages > 0)
                {
                    foreach (var item in await receiver.ReceiveBatchAsync(remainingMessages))
                    {
                        remainingMessages--;
                        messageEnum.MoveNext();
                        Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId);
                        Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId);
                        await receiver.DeadLetterAsync(item.LockToken, "testReason", "testDescription");
                    }
                }
                Assert.AreEqual(0, remainingMessages);

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

                messageEnum.Reset();
                remainingMessages = messageCount;
                var deadLetterReceiver = client.CreateDeadLetterReceiver(scope.QueueName);

                while (remainingMessages > 0)
                {
                    foreach (var msg in await deadLetterReceiver.ReceiveBatchAsync(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.CompleteAsync(msg.LockToken);
                    }
                }
                Assert.AreEqual(0, remainingMessages);

                var deadLetterMessage = await deadLetterReceiver.PeekAsync();

                Assert.IsNull(deadLetterMessage);
            }
        }
        public async Task AutoLockRenewalWorks(int numThreads)
        {
            var lockDuration = TimeSpan.FromSeconds(10);

            await using (var scope = await ServiceBusScope.CreateWithQueue(
                             enablePartitioning: false,
                             enableSession: true,
                             lockDuration: lockDuration))
            {
                await using var client = GetClient();
                ServiceBusSender sender = client.CreateSender(scope.QueueName);

                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                var messageSendCt = numThreads;
                for (int i = 0; i < numThreads; i++)
                {
                    AddMessages(batch, 1, Guid.NewGuid().ToString());
                }

                await sender.SendBatchAsync(batch);

                var options = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = numThreads,
                    AutoComplete       = false
                };
                var processor = client.CreateSessionProcessor(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(ProcessSessionMessageEventArgs args)
                {
                    try
                    {
                        var message     = args.Message;
                        var lockedUntil = args.SessionLockedUntil;
                        await Task.Delay(lockDuration);

                        Assert.That(args.SessionLockedUntil > lockedUntil, $"{lockedUntil},{DateTime.UtcNow}");
                        await args.CompleteAsync(message, args.CancellationToken);

                        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();

                Assert.AreEqual(numThreads, messageCt);
            }
        }
        public async Task ProcessSessionEvent(int numThreads, bool autoComplete)
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(
                             enablePartitioning: false,
                             enableSession: true))
            {
                await using var client = GetClient();
                ServiceBusSender sender = client.CreateSender(scope.QueueName);

                // send 1 message for each thread and use a different session for each message
                ConcurrentDictionary <string, bool> sessions = new ConcurrentDictionary <string, bool>();
                for (int i = 0; i < numThreads; i++)
                {
                    var sessionId = Guid.NewGuid().ToString();
                    await sender.SendAsync(GetMessage(sessionId));

                    sessions.TryAdd(sessionId, true);
                }
                var options = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = numThreads,
                    AutoComplete       = autoComplete
                };
                var processor = client.CreateSessionProcessor(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(ProcessSessionMessageEventArgs args)
                {
                    try
                    {
                        var message = args.Message;
                        if (!autoComplete)
                        {
                            await args.CompleteAsync(message);
                        }
                        Interlocked.Increment(ref messageCt);
                        sessions.TryRemove(message.SessionId, out bool _);
                        Assert.AreEqual(message.SessionId, args.SessionId);
                        Assert.IsNotNull(args.SessionLockedUntil);
                    }
                    finally
                    {
                        var setIndex = Interlocked.Increment(ref completionSourceIndex);
                        completionSources[setIndex].SetResult(true);
                    }
                }

                await Task.WhenAll(completionSources.Select(source => source.Task));

                await processor.StopProcessingAsync();

                // there is only one message for each session, and one
                // thread for each session, so the total messages processed
                // should equal the number of threads
                Assert.AreEqual(numThreads, messageCt);

                // we should have received messages from each of the sessions
                Assert.AreEqual(0, sessions.Count);
            }
        }
 internal AzureSenderServiceBus(ServiceBusSender serviceBusSender)
 {
     _serviceBusSender = serviceBusSender;
 }
 internal static ISenderMessageBus Wrap(ServiceBusSender sender)
 {
     return(new AzureSenderServiceBus(sender));
 }
Ejemplo n.º 10
0
        public async Task ManageRules()
        {
            await using (var scope = await ServiceBusScope.CreateWithTopic(enablePartitioning: false, enableSession: false))
            {
                #region Snippet:ServiceBusManageRules
#if SNIPPET
                string connectionString = "<connection_string>";
                string topicName        = "<topic_name>";
                string subscriptionName = "<subscription_name>";
#else
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string topicName        = scope.TopicName;
                string subscriptionName = scope.SubscriptionNames.First();
#endif

                await using var client = new ServiceBusClient(connectionString);

                await using ServiceBusRuleManager ruleManager = client.CreateRuleManager(topicName, subscriptionName);

                // By default, subscriptions are created with a default rule that always evaluates to True. In order to filter, we need
                // to delete the default rule. You can skip this step if you create the subscription with the ServiceBusAdministrationClient,
                // and specify a the FalseRuleFilter in the create rule options.
                await ruleManager.DeleteRuleAsync(RuleProperties.DefaultRuleName);

                await ruleManager.CreateRuleAsync("brand-filter", new CorrelationRuleFilter { Subject = "Toyota" });

                // create the sender
                ServiceBusSender sender = client.CreateSender(topicName);

                ServiceBusMessage[] messages =
                {
                    new ServiceBusMessage {
                        Subject = "Ford", ApplicationProperties ={                         { "Price", 25000 } }
                    },
                    new ServiceBusMessage {
                        Subject = "Toyota", ApplicationProperties ={                         { "Price", 28000 } }
                    },
                    new ServiceBusMessage {
                        Subject = "Honda", ApplicationProperties ={                         { "Price", 35000 } }
                    }
                };

                // send the messages
                await sender.SendMessagesAsync(messages);

                // create a receiver for our subscription that we can use to receive and settle the message
                ServiceBusReceiver receiver = client.CreateReceiver(topicName, subscriptionName);

                // receive the message - we only get back the Toyota message
                while (true)
                {
                    ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync(TimeSpan.FromSeconds(5));

                    if (receivedMessage == null)
                    {
                        break;
                    }
                    Console.WriteLine($"Brand: {receivedMessage.Subject}, Price: {receivedMessage.ApplicationProperties["Price"]}");
                    await receiver.CompleteMessageAsync(receivedMessage);
                }

                await ruleManager.CreateRuleAsync("price-filter", new SqlRuleFilter("Price < 30000"));

                await ruleManager.DeleteRuleAsync("brand-filter");

                // we can also use the rule manager to iterate over the rules on the subscription.
                await foreach (RuleProperties rule in ruleManager.GetRulesAsync())
                {
                    // we should only have 1 rule at this point - "price-filter"
                    Console.WriteLine(rule.Name);
                }

                // send the messages again - because the subscription rules are evaluated when the messages are first enqueued, adding rules
                // for messages that are already in a subscription would have no effect.
                await sender.SendMessagesAsync(messages);

                // receive the messages - we get back both the Ford and the Toyota
                while (true)
                {
                    ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync(TimeSpan.FromSeconds(5));

                    if (receivedMessage == null)
                    {
                        break;
                    }
                    Console.WriteLine($"Brand: {receivedMessage.Subject}, Price: {receivedMessage.ApplicationProperties["Price"]}");
                }
                #endregion
            }
        }
        public async Task ProcessEvent(int numThreads, bool autoComplete)
        {
            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);

                // 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.CreateBatchAsync();

                var messageSendCt = numThreads * 2;
                ServiceBusMessageBatch messageBatch = AddMessages(batch, messageSendCt);

                await sender.SendBatchAsync(messageBatch);

                var options = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = numThreads,
                    AutoComplete       = autoComplete
                };
                var processor = client.GetProcessor(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;
                        if (!autoComplete)
                        {
                            var lockedUntil = message.LockedUntil;
                            await args.RenewMessageLockAsync(message);

                            Assert.That(message.LockedUntil > lockedUntil);
                            await args.CompleteAsync(message, args.CancellationToken);
                        }
                        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);
            }
        }
 public PatientsController(PrDataContext context, ServiceBusSender sender)
 {
     _context = context;
     _sender  = sender;
 }
        public async Task GetSubscriptionRuntimeInfoTest()
        {
            var topicName        = nameof(GetSubscriptionRuntimeInfoTest).ToLower() + Guid.NewGuid().ToString("D").Substring(0, 8);
            var subscriptionName = Guid.NewGuid().ToString("D").Substring(0, 8);
            var mgmtClient       = new ServiceBusManagementClient(TestEnvironment.ServiceBusConnectionString);

            await using var sbClient = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);

            TopicDescription topicDescription = await mgmtClient.CreateTopicAsync(topicName);

            // Changing Last Updated Time
            topicDescription.AutoDeleteOnIdle = TimeSpan.FromMinutes(100);
            await mgmtClient.UpdateTopicAsync(topicDescription);

            SubscriptionDescription subscriptionDescription = await mgmtClient.CreateSubscriptionAsync(topicName, subscriptionName);

            // Changing Last Updated Time for subscription
            subscriptionDescription.AutoDeleteOnIdle = TimeSpan.FromMinutes(100);
            await mgmtClient.UpdateSubscriptionAsync(subscriptionDescription);

            // Populating 1 active message, 1 dead letter message and 1 scheduled message
            // Changing Last Accessed Time

            ServiceBusSender sender = sbClient.CreateSender(topicName);
            await sender.SendMessageAsync(new ServiceBusMessage()
            {
                MessageId = "1"
            });

            await sender.SendMessageAsync(new ServiceBusMessage()
            {
                MessageId = "2"
            });

            await sender.SendMessageAsync(new ServiceBusMessage()
            {
                MessageId = "3", ScheduledEnqueueTime = DateTime.UtcNow.AddDays(1)
            });

            ServiceBusReceiver        receiver = sbClient.CreateReceiver(topicName, subscriptionName);
            ServiceBusReceivedMessage msg      = await receiver.ReceiveMessageAsync();

            await receiver.DeadLetterMessageAsync(msg.LockToken);

            List <SubscriptionRuntimeInfo> runtimeInfoList = new List <SubscriptionRuntimeInfo>();

            await foreach (SubscriptionRuntimeInfo subscriptionRuntimeInfo in mgmtClient.GetSubscriptionsRuntimeInfoAsync(topicName))
            {
                runtimeInfoList.Add(subscriptionRuntimeInfo);
            }
            runtimeInfoList = runtimeInfoList.Where(e => e.TopicName.StartsWith(nameof(GetSubscriptionRuntimeInfoTest).ToLower())).ToList();
            Assert.True(runtimeInfoList.Count == 1, $"Expected 1 subscription but {runtimeInfoList.Count} subscriptions returned");
            SubscriptionRuntimeInfo runtimeInfo = runtimeInfoList.First();

            Assert.NotNull(runtimeInfo);

            Assert.AreEqual(topicName, runtimeInfo.TopicName);
            Assert.AreEqual(subscriptionName, runtimeInfo.SubscriptionName);

            Assert.True(runtimeInfo.CreatedAt < runtimeInfo.UpdatedAt);
            Assert.True(runtimeInfo.UpdatedAt < runtimeInfo.AccessedAt);

            Assert.AreEqual(1, runtimeInfo.CountDetails.ActiveMessageCount);
            Assert.AreEqual(1, runtimeInfo.CountDetails.DeadLetterMessageCount);
            Assert.AreEqual(0, runtimeInfo.CountDetails.ScheduledMessageCount);
            Assert.AreEqual(2, runtimeInfo.MessageCount);

            SubscriptionRuntimeInfo singleRuntimeInfo = await mgmtClient.GetSubscriptionRuntimeInfoAsync(topicName, subscriptionName);

            Assert.AreEqual(runtimeInfo.CreatedAt, singleRuntimeInfo.CreatedAt);
            Assert.AreEqual(runtimeInfo.AccessedAt, singleRuntimeInfo.AccessedAt);
            Assert.AreEqual(runtimeInfo.UpdatedAt, singleRuntimeInfo.UpdatedAt);
            Assert.AreEqual(runtimeInfo.SubscriptionName, singleRuntimeInfo.SubscriptionName);
            Assert.AreEqual(runtimeInfo.MessageCount, singleRuntimeInfo.MessageCount);
            Assert.AreEqual(runtimeInfo.CountDetails.ActiveMessageCount, singleRuntimeInfo.CountDetails.ActiveMessageCount);
            Assert.AreEqual(runtimeInfo.CountDetails.DeadLetterMessageCount, singleRuntimeInfo.CountDetails.DeadLetterMessageCount);
            Assert.AreEqual(runtimeInfo.CountDetails.ScheduledMessageCount, singleRuntimeInfo.CountDetails.ScheduledMessageCount);
            Assert.AreEqual(runtimeInfo.TopicName, singleRuntimeInfo.TopicName);

            await mgmtClient.DeleteTopicAsync(topicName);
        }
        public async Task SenderReceiverActivities(bool useSessions)
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: useSessions))
            {
                var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
                ServiceBusSender sender    = client.CreateSender(scope.QueueName);
                string           sessionId = null;
                if (useSessions)
                {
                    sessionId = "sessionId";
                }
                int numMessages = 5;
                var msgs        = ServiceBusTestUtilities.GetMessages(numMessages, sessionId);
                await sender.SendMessagesAsync(msgs);

                Activity[] sendActivities = AssertSendActivities(useSessions, sender, msgs);

                ServiceBusReceiver receiver = null;
                if (useSessions)
                {
                    receiver = await client.AcceptNextSessionAsync(scope.QueueName);
                }
                else
                {
                    receiver = client.CreateReceiver(scope.QueueName);
                }

                var remaining = numMessages;
                List <ServiceBusReceivedMessage> receivedMsgs = new List <ServiceBusReceivedMessage>();
                while (remaining > 0)
                {
                    // loop in case we don't receive all messages in one attempt
                    var received = await receiver.ReceiveMessagesAsync(remaining);

                    receivedMsgs.AddRange(received);
                    var receiveScope = _listener.AssertAndRemoveScope(DiagnosticProperty.ReceiveActivityName);
                    AssertCommonTags(receiveScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace);

                    var receiveLinkedActivities = receiveScope.LinkedActivities;
                    for (int i = 0; i < receiveLinkedActivities.Count; i++)
                    {
                        Assert.AreEqual(sendActivities[i].ParentId, receiveLinkedActivities[i].ParentId);
                    }
                    remaining -= received.Count;
                }

                var msgIndex = 0;

                var completed = receivedMsgs[msgIndex];
                await receiver.CompleteMessageAsync(completed);

                var completeScope = _listener.AssertAndRemoveScope(DiagnosticProperty.CompleteActivityName);
                AssertCommonTags(completeScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace);

                var deferred = receivedMsgs[++msgIndex];
                await receiver.DeferMessageAsync(deferred);

                var deferredScope = _listener.AssertAndRemoveScope(DiagnosticProperty.DeferActivityName);
                AssertCommonTags(deferredScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace);

                var deadLettered = receivedMsgs[++msgIndex];
                await receiver.DeadLetterMessageAsync(deadLettered);

                var deadLetterScope = _listener.AssertAndRemoveScope(DiagnosticProperty.DeadLetterActivityName);
                AssertCommonTags(deadLetterScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace);

                var abandoned = receivedMsgs[++msgIndex];
                await receiver.AbandonMessageAsync(abandoned);

                var abandonScope = _listener.AssertAndRemoveScope(DiagnosticProperty.AbandonActivityName);
                AssertCommonTags(abandonScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace);

                var receiveDeferMsg = await receiver.ReceiveDeferredMessageAsync(deferred.SequenceNumber);

                var receiveDeferScope = _listener.AssertAndRemoveScope(DiagnosticProperty.ReceiveDeferredActivityName);
                AssertCommonTags(receiveDeferScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace);

                // renew lock
                if (useSessions)
                {
                    var sessionReceiver = (ServiceBusSessionReceiver)receiver;
                    await sessionReceiver.RenewSessionLockAsync();

                    var renewSessionScope = _listener.AssertAndRemoveScope(DiagnosticProperty.RenewSessionLockActivityName);
                    AssertCommonTags(renewSessionScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace);

                    // set state
                    var state = new BinaryData("state");
                    await sessionReceiver.SetSessionStateAsync(state);

                    var setStateScope = _listener.AssertAndRemoveScope(DiagnosticProperty.SetSessionStateActivityName);
                    AssertCommonTags(setStateScope.Activity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace);

                    // get state
                    var getState = await sessionReceiver.GetSessionStateAsync();

                    Assert.AreEqual(state.ToArray(), getState.ToArray());
                    var getStateScope = _listener.AssertAndRemoveScope(DiagnosticProperty.GetSessionStateActivityName);
                    AssertCommonTags(getStateScope.Activity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace);
                }
                else
                {
                    await receiver.RenewMessageLockAsync(receivedMsgs[4]);

                    var renewMessageScope = _listener.AssertAndRemoveScope(DiagnosticProperty.RenewMessageLockActivityName);
                    AssertCommonTags(renewMessageScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace);
                }

                // schedule
                msgs = ServiceBusTestUtilities.GetMessages(numMessages, sessionId);

                foreach (var msg in msgs)
                {
                    var seq = await sender.ScheduleMessageAsync(msg, DateTimeOffset.UtcNow.AddMinutes(1));

                    Assert.IsNotNull(msg.ApplicationProperties[DiagnosticProperty.DiagnosticIdAttribute]);

                    var messageScope = _listener.AssertAndRemoveScope(DiagnosticProperty.MessageActivityName);
                    AssertCommonTags(messageScope.Activity, sender.EntityPath, sender.FullyQualifiedNamespace);

                    var scheduleScope = _listener.AssertAndRemoveScope(DiagnosticProperty.ScheduleActivityName);
                    AssertCommonTags(scheduleScope.Activity, sender.EntityPath, sender.FullyQualifiedNamespace);

                    var linkedActivities = scheduleScope.LinkedActivities;
                    Assert.AreEqual(1, linkedActivities.Count);
                    Assert.AreEqual(messageScope.Activity.Id, linkedActivities[0].ParentId);

                    await sender.CancelScheduledMessageAsync(seq);

                    var cancelScope = _listener.AssertAndRemoveScope(DiagnosticProperty.CancelActivityName);
                    AssertCommonTags(cancelScope.Activity, sender.EntityPath, sender.FullyQualifiedNamespace);
                }

                // send a batch
                var batch = await sender.CreateMessageBatchAsync();

                for (int i = 0; i < numMessages; i++)
                {
                    batch.TryAddMessage(ServiceBusTestUtilities.GetMessage(sessionId));
                }
                await sender.SendMessagesAsync(batch);

                AssertSendActivities(useSessions, sender, batch.AsEnumerable <ServiceBusMessage>());
            };
        }
        public async Task ProcessEventConsumesAllMessages(int numThreads, bool autoComplete)
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(
                             enablePartitioning: false,
                             enableSession: true))
            {
                await using var client = GetClient();
                ServiceBusSender sender = client.CreateSender(scope.QueueName);

                // send 1 message for each thread and use a different session for each message
                ConcurrentDictionary <string, bool> sessions = new ConcurrentDictionary <string, bool>();
                for (int i = 0; i < numThreads; i++)
                {
                    var sessionId = Guid.NewGuid().ToString();
                    await sender.SendAsync(GetMessage(sessionId));

                    sessions.TryAdd(sessionId, true);
                }

                int messageCt = 0;

                TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                var options = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = numThreads,
                    AutoComplete       = autoComplete
                };

                ServiceBusSessionProcessor processor = GetNoRetryClient().CreateSessionProcessor(scope.QueueName, options);

                processor.ProcessMessageAsync += ProcessMessage;
                processor.ProcessErrorAsync   += ExceptionHandler;
                await processor.StartProcessingAsync();

                async Task ProcessMessage(ProcessSessionMessageEventArgs args)
                {
                    try
                    {
                        var message = args.Message;
                        if (!autoComplete)
                        {
                            await args.CompleteAsync(message);
                        }
                        sessions.TryRemove(message.SessionId, out bool _);
                        Assert.AreEqual(message.SessionId, args.SessionId);
                        Assert.IsNotNull(args.SessionLockedUntil);
                    }
                    finally
                    {
                        var ct = Interlocked.Increment(ref messageCt);
                        if (ct == numThreads)
                        {
                            taskCompletionSource.SetResult(true);
                        }
                    }
                }

                await taskCompletionSource.Task;
                await processor.StopProcessingAsync();

                Assert.AreEqual(numThreads, messageCt);

                // we should have received messages from each of the sessions
                Assert.AreEqual(0, sessions.Count);

                // try receiving to verify empty
                // since all the messages are gone and we are using sessions, we won't actually
                // be able to open the Receive link
                // only do this assertion when we complete the message ourselves,
                // otherwise the message completion may have been cancelled if it didn't finish
                // before calling StopProcessingAsync.


                if (!autoComplete)
                {
                    Assert.That(async() =>
                                await GetNoRetryClient().CreateSessionReceiverAsync(scope.QueueName),
                                Throws.Exception);
                }
            }
        }
 public AutobarnAzureServiceBus(ServiceBusClient client, string topic)
 {
     sender = client.CreateSender(topic);
 }
        public async Task Process_Event_SessionId(int numThreads, bool autoComplete)
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(
                             enablePartitioning: false,
                             enableSession: true))
            {
                await using var client = GetClient();
                ServiceBusSender sender = client.CreateSender(scope.QueueName);

                // send 1 message for each thread and use a different session for each message
                ConcurrentDictionary <string, bool> sessions = new ConcurrentDictionary <string, bool>();
                string sessionId = null;
                for (int i = 0; i < numThreads; i++)
                {
                    sessionId = Guid.NewGuid().ToString();
                    await sender.SendAsync(GetMessage(sessionId));

                    sessions.TryAdd(sessionId, true);
                }

                int messageCt = 0;

                TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                var options = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = numThreads,
                    AutoComplete       = autoComplete,
                };

                var processor = client.CreateSessionProcessor(
                    scope.QueueName,
                    options,
                    sessionId); // using the last sessionId from the loop

                processor.ProcessMessageAsync += ProcessMessage;
                processor.ProcessErrorAsync   += ExceptionHandler;
                await processor.StartProcessingAsync();

                async Task ProcessMessage(ProcessSessionMessageEventArgs args)
                {
                    try
                    {
                        var message = args.Message;
                        if (!autoComplete)
                        {
                            await args.CompleteAsync(message);
                        }
                        sessions.TryRemove(message.SessionId, out bool _);
                        Assert.AreEqual(sessionId, message.SessionId);
                        Assert.AreEqual(sessionId, args.SessionId);
                        Assert.IsNotNull(args.SessionLockedUntil);
                    }
                    finally
                    {
                        var ct = Interlocked.Increment(ref messageCt);
                        tcs.SetResult(true);
                    }
                }

                await tcs.Task;
                await processor.StopProcessingAsync();

                // only one message has the session id that we
                // configured the processor with
                Assert.AreEqual(1, messageCt);

                // we should have received messages from only the specified session
                Assert.AreEqual(numThreads - 1, sessions.Count);
            }
        }
Ejemplo n.º 18
0
        public async Task ReceiverThrowsAfterSessionLockLost(bool isSessionSpecified)
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true, lockDuration: TimeSpan.FromSeconds(5)))
            {
                await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
                ServiceBusSender sender = client.CreateSender(scope.QueueName);
                var sessionId1          = "sessionId1";

                await sender.SendMessageAsync(GetMessage(sessionId1));

                // send another session message before the one we are interested in to make sure that when isSessionSpecified=true, it is being respected
                await sender.SendMessageAsync(GetMessage("sessionId2"));

                ServiceBusSessionReceiver receiver = await client.CreateSessionReceiverAsync(
                    scope.QueueName,
                    new ServiceBusSessionReceiverOptions
                {
                    SessionId = isSessionSpecified ? sessionId1 : null
                });

                if (isSessionSpecified)
                {
                    Assert.AreEqual(sessionId1, receiver.SessionId);
                }

                var message = await receiver.ReceiveMessageAsync();

                await Task.Delay((receiver.SessionLockedUntil - DateTime.UtcNow) + TimeSpan.FromSeconds(5));

                Assert.That(async() => await receiver.ReceiveMessageAsync(),
                            Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason))
                            .EqualTo(ServiceBusException.FailureReason.SessionLockLost));

                Assert.That(async() => await receiver.SetSessionStateAsync(null),
                            Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason))
                            .EqualTo(ServiceBusException.FailureReason.SessionLockLost));

                Assert.That(async() => await receiver.GetSessionStateAsync(),
                            Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason))
                            .EqualTo(ServiceBusException.FailureReason.SessionLockLost));

                Assert.That(async() => await receiver.CompleteMessageAsync(message),
                            Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason))
                            .EqualTo(ServiceBusException.FailureReason.SessionLockLost));

                Assert.That(async() => await receiver.CompleteMessageAsync(message),
                            Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason))
                            .EqualTo(ServiceBusException.FailureReason.SessionLockLost));

                Assert.That(async() => await receiver.DeadLetterMessageAsync(message),
                            Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason))
                            .EqualTo(ServiceBusException.FailureReason.SessionLockLost));

                Assert.That(async() => await receiver.DeferMessageAsync(message),
                            Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason))
                            .EqualTo(ServiceBusException.FailureReason.SessionLockLost));

                Assert.That(async() => await receiver.AbandonMessageAsync(message),
                            Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason))
                            .EqualTo(ServiceBusException.FailureReason.SessionLockLost));
            }
        }
        public async Task MaxAutoLockRenewalDurationRespected(int numThreads, int autoLockRenewalDuration)
        {
            var lockDuration = TimeSpan.FromSeconds(10);

            await using (var scope = await ServiceBusScope.CreateWithQueue(
                             enablePartitioning: false,
                             enableSession: true,
                             lockDuration: lockDuration))
            {
                await using var client = GetClient();
                ServiceBusSender sender = client.CreateSender(scope.QueueName);

                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                var messageSendCt = numThreads;
                for (int i = 0; i < numThreads; i++)
                {
                    AddMessages(batch, 1, Guid.NewGuid().ToString());
                }

                await sender.SendBatchAsync(batch);

                var options = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls         = numThreads,
                    AutoComplete               = false,
                    MaxAutoLockRenewalDuration = TimeSpan.FromSeconds(autoLockRenewalDuration)
                };
                var processor = client.CreateSessionProcessor(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(ProcessSessionMessageEventArgs args)
                {
                    try
                    {
                        var message     = args.Message;
                        var lockedUntil = args.SessionLockedUntil;
                        await Task.Delay(lockDuration.Add(TimeSpan.FromSeconds(1)));

                        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, args.SessionLockedUntil);
                            Assert.That(
                                async() => await args.CompleteAsync(message, args.CancellationToken),
                                Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)).EqualTo(ServiceBusException.FailureReason.SessionLockLost));
                            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();

                Assert.AreEqual(numThreads, messageCt);
            }
        }
        public async Task SenderReceiverActivities(bool useSessions)
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: useSessions))
            {
                var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
                ServiceBusSender sender    = client.CreateSender(scope.QueueName);
                string           sessionId = null;
                if (useSessions)
                {
                    sessionId = "sessionId";
                }
                int numMessages = 5;
                var msgs        = GetMessages(numMessages, sessionId);
                await sender.SendMessagesAsync(msgs);

                Activity[] sendActivities = AssertSendActivities(useSessions, sender, msgs);

                ServiceBusReceiver receiver = null;
                if (useSessions)
                {
                    receiver = await client.CreateSessionReceiverAsync(scope.QueueName);
                }
                else
                {
                    receiver = client.CreateReceiver(scope.QueueName);
                }

                var remaining = numMessages;
                List <ServiceBusReceivedMessage> receivedMsgs = new List <ServiceBusReceivedMessage>();
                while (remaining > 0)
                {
                    // loop in case we don't receive all messages in one attempt
                    var received = await receiver.ReceiveMessagesAsync(remaining);

                    receivedMsgs.AddRange(received);
                    (string Key, object Value, DiagnosticListener)receiveStart = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.ReceiveActivityName + ".Start", receiveStart.Key);

                    Activity receiveActivity = (Activity)receiveStart.Value;
                    AssertCommonTags(receiveActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace);
                    CollectionAssert.Contains(
                        receiveActivity.Tags,
                        new KeyValuePair <string, string>(
                            DiagnosticProperty.RequestedMessageCountAttribute,
                            remaining.ToString()));
                    CollectionAssert.Contains(
                        receiveActivity.Tags,
                        new KeyValuePair <string, string>(
                            DiagnosticProperty.MessageIdAttribute,
                            string.Join(",", received.Select(m => m.MessageId).ToArray())));
                    remaining -= received.Count;

                    if (useSessions)
                    {
                        CollectionAssert.Contains(
                            receiveActivity.Tags,
                            new KeyValuePair <string, string>(
                                DiagnosticProperty.SessionIdAttribute,
                                string.Join(",", msgs.Select(m => m.SessionId).Distinct().ToArray())));
                    }
                    var receiveLinkedActivities = ((IEnumerable <Activity>)receiveActivity.GetType().GetProperty("Links").GetValue(receiveActivity)).ToArray();
                    for (int i = 0; i < receiveLinkedActivities.Length; i++)
                    {
                        Assert.AreEqual(sendActivities[i].ParentId, receiveLinkedActivities[i].ParentId);
                    }
                    (string Key, object Value, DiagnosticListener)receiveStop = _listener.Events.Dequeue();

                    Assert.AreEqual(DiagnosticProperty.ReceiveActivityName + ".Stop", receiveStop.Key);
                }

                var msgIndex = 0;

                var completed = receivedMsgs[msgIndex];
                await receiver.CompleteMessageAsync(completed);

                (string Key, object Value, DiagnosticListener)completeStart = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.CompleteActivityName + ".Start", completeStart.Key);
                Activity completeActivity = (Activity)completeStart.Value;
                AssertCommonTags(completeActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace);
                AssertLockTokensTag(completeActivity, completed.LockToken);
                (string Key, object Value, DiagnosticListener)completeStop = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.CompleteActivityName + ".Stop", completeStop.Key);

                var deferred = receivedMsgs[++msgIndex];
                await receiver.DeferMessageAsync(deferred);

                (string Key, object Value, DiagnosticListener)deferStart = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.DeferActivityName + ".Start", deferStart.Key);
                Activity deferActivity = (Activity)deferStart.Value;
                AssertCommonTags(deferActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace);
                AssertLockTokensTag(deferActivity, deferred.LockToken);
                (string Key, object Value, DiagnosticListener)deferStop = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.DeferActivityName + ".Stop", deferStop.Key);

                var deadLettered = receivedMsgs[++msgIndex];
                await receiver.DeadLetterMessageAsync(deadLettered);

                (string Key, object Value, DiagnosticListener)deadLetterStart = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.DeadLetterActivityName + ".Start", deadLetterStart.Key);
                Activity deadLetterActivity = (Activity)deadLetterStart.Value;
                AssertCommonTags(deadLetterActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace);
                AssertLockTokensTag(deadLetterActivity, deadLettered.LockToken);
                (string Key, object Value, DiagnosticListener)deadletterStop = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.DeadLetterActivityName + ".Stop", deadletterStop.Key);

                var abandoned = receivedMsgs[++msgIndex];
                await receiver.AbandonMessageAsync(abandoned);

                (string Key, object Value, DiagnosticListener)abandonStart = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.AbandonActivityName + ".Start", abandonStart.Key);
                Activity abandonActivity = (Activity)abandonStart.Value;
                AssertCommonTags(abandonActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace);
                AssertLockTokensTag(abandonActivity, abandoned.LockToken);
                (string Key, object Value, DiagnosticListener)abandonStop = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.AbandonActivityName + ".Stop", abandonStop.Key);

                var receiveDeferMsg = await receiver.ReceiveDeferredMessageAsync(deferred.SequenceNumber);

                (string Key, object Value, DiagnosticListener)receiveDeferStart = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.ReceiveDeferredActivityName + ".Start", receiveDeferStart.Key);
                Activity receiveDeferActivity = (Activity)receiveDeferStart.Value;
                AssertCommonTags(receiveDeferActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace);
                CollectionAssert.Contains(
                    receiveDeferActivity.Tags,
                    new KeyValuePair <string, string>(
                        DiagnosticProperty.MessageIdAttribute,
                        deferred.MessageId));
                CollectionAssert.Contains(
                    receiveDeferActivity.Tags,
                    new KeyValuePair <string, string>(
                        DiagnosticProperty.SequenceNumbersAttribute,
                        deferred.SequenceNumber.ToString()));
                (string Key, object Value, DiagnosticListener)receiveDeferStop = _listener.Events.Dequeue();
                Assert.AreEqual(DiagnosticProperty.ReceiveDeferredActivityName + ".Stop", receiveDeferStop.Key);

                // renew lock
                if (useSessions)
                {
                    var sessionReceiver = (ServiceBusSessionReceiver)receiver;
                    await sessionReceiver.RenewSessionLockAsync();

                    (string Key, object Value, DiagnosticListener)renewStart = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.RenewSessionLockActivityName + ".Start", renewStart.Key);
                    Activity renewActivity = (Activity)renewStart.Value;
                    AssertCommonTags(renewActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace);
                    CollectionAssert.Contains(
                        renewActivity.Tags,
                        new KeyValuePair <string, string>(
                            DiagnosticProperty.SessionIdAttribute,
                            "sessionId"));

                    (string Key, object Value, DiagnosticListener)renewStop = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.RenewSessionLockActivityName + ".Stop", renewStop.Key);

                    // set state
                    var state = Encoding.UTF8.GetBytes("state");
                    await sessionReceiver.SetSessionStateAsync(state);

                    (string Key, object Value, DiagnosticListener)setStateStart = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.SetSessionStateActivityName + ".Start", setStateStart.Key);
                    Activity setStateActivity = (Activity)setStateStart.Value;
                    AssertCommonTags(setStateActivity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace);
                    CollectionAssert.Contains(
                        setStateActivity.Tags,
                        new KeyValuePair <string, string>(
                            DiagnosticProperty.SessionIdAttribute,
                            "sessionId"));

                    (string Key, object Value, DiagnosticListener)setStateStop = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.SetSessionStateActivityName + ".Stop", setStateStop.Key);

                    // get state
                    var getState = await sessionReceiver.GetSessionStateAsync();

                    Assert.AreEqual(state, getState);
                    (string Key, object Value, DiagnosticListener)getStateStart = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.GetSessionStateActivityName + ".Start", getStateStart.Key);
                    Activity getStateActivity = (Activity)getStateStart.Value;
                    AssertCommonTags(getStateActivity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace);
                    CollectionAssert.Contains(
                        getStateActivity.Tags,
                        new KeyValuePair <string, string>(
                            DiagnosticProperty.SessionIdAttribute,
                            "sessionId"));

                    (string Key, object Value, DiagnosticListener)getStateStop = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.GetSessionStateActivityName + ".Stop", getStateStop.Key);
                }
                else
                {
                    await receiver.RenewMessageLockAsync(receivedMsgs[4]);

                    (string Key, object Value, DiagnosticListener)renewStart = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.RenewMessageLockActivityName + ".Start", renewStart.Key);
                    Activity renewActivity = (Activity)renewStart.Value;
                    AssertCommonTags(renewActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace);
                    AssertLockTokensTag(renewActivity, receivedMsgs[4].LockToken);
                    CollectionAssert.Contains(
                        renewActivity.Tags,
                        new KeyValuePair <string, string>(
                            DiagnosticProperty.LockedUntilAttribute,
                            receivedMsgs[4].LockedUntil.ToString()));

                    (string Key, object Value, DiagnosticListener)renewStop = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.RenewMessageLockActivityName + ".Stop", renewStop.Key);
                }

                // schedule
                msgs = GetMessages(numMessages, sessionId);

                foreach (var msg in msgs)
                {
                    var seq = await sender.ScheduleMessageAsync(msg, DateTimeOffset.UtcNow.AddMinutes(1));

                    Assert.IsNotNull(msg.ApplicationProperties[DiagnosticProperty.DiagnosticIdAttribute]);

                    (string Key, object Value, DiagnosticListener)startMessage = _listener.Events.Dequeue();
                    Activity messageActivity = (Activity)startMessage.Value;
                    AssertCommonTags(messageActivity, sender.EntityPath, sender.FullyQualifiedNamespace);
                    Assert.AreEqual(DiagnosticProperty.MessageActivityName + ".Start", startMessage.Key);

                    (string Key, object Value, DiagnosticListener)stopMessage = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.MessageActivityName + ".Stop", stopMessage.Key);

                    (string Key, object Value, DiagnosticListener)startSchedule = _listener.Events.Dequeue();
                    AssertCommonTags((Activity)startSchedule.Value, sender.EntityPath, sender.FullyQualifiedNamespace);

                    Assert.AreEqual(DiagnosticProperty.ScheduleActivityName + ".Start", startSchedule.Key);
                    (string Key, object Value, DiagnosticListener)stopSchedule = _listener.Events.Dequeue();

                    Assert.AreEqual(DiagnosticProperty.ScheduleActivityName + ".Stop", stopSchedule.Key);
                    var linkedActivities = ((IEnumerable <Activity>)startSchedule.Value.GetType().GetProperty("Links").GetValue(startSchedule.Value)).ToArray();
                    Assert.AreEqual(1, linkedActivities.Length);
                    Assert.AreEqual(messageActivity.Id, linkedActivities[0].ParentId);

                    await sender.CancelScheduledMessageAsync(seq);

                    (string Key, object Value, DiagnosticListener)startCancel = _listener.Events.Dequeue();
                    AssertCommonTags((Activity)startCancel.Value, sender.EntityPath, sender.FullyQualifiedNamespace);
                    Assert.AreEqual(DiagnosticProperty.CancelActivityName + ".Start", startCancel.Key);

                    (string Key, object Value, DiagnosticListener)stopCancel = _listener.Events.Dequeue();
                    Assert.AreEqual(DiagnosticProperty.CancelActivityName + ".Stop", stopCancel.Key);
                }

                // send a batch
                var batch = await sender.CreateMessageBatchAsync();

                for (int i = 0; i < numMessages; i++)
                {
                    batch.TryAddMessage(GetMessage(sessionId));
                }
                await sender.SendMessagesAsync(batch);

                AssertSendActivities(useSessions, sender, batch.AsEnumerable <ServiceBusMessage>());
            };
        }
Ejemplo n.º 21
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.
                    AutoComplete = false,

                    // I can also allow for multi-threading
                    MaxConcurrentCalls = 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);
                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.CompleteAsync(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(Encoding.Default.GetBytes("some state"));

                    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 SendServiceBusQueueMessage()
        {
            ServiceBusSender sender = _serviceBusClient.CreateSender(_settings.ServiceBusQueueName);

            await sender.SendMessageAsync(new ServiceBusMessage($"Test message {Guid.NewGuid()} ({DateTime.UtcNow:HH:mm:ss})"));
        }
Ejemplo n.º 23
0
        public async Task ReceiverCanReconnectToSameSession(bool isSessionSpecified)
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true, lockDuration: TimeSpan.FromSeconds(5)))
            {
                await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
                ServiceBusSender sender = client.CreateSender(scope.QueueName);

                await sender.SendMessagesAsync(GetMessages(3, "sessionId1"));

                // send another session message before the one we are interested in to make sure that when isSessionSpecified=true, it is being respected
                await sender.SendMessagesAsync(GetMessages(3, "sessionId2"));

                ServiceBusSessionReceiver receiver = await client.AcceptSessionAsync(
                    scope.QueueName,
                    isSessionSpecified? "sessionId1" : null);

                if (isSessionSpecified)
                {
                    Assert.AreEqual("sessionId1", receiver.SessionId);
                }

                var firstMessage = await receiver.ReceiveMessageAsync();

                Assert.AreEqual(receiver.SessionId, firstMessage.SessionId);
                var sessionId = receiver.SessionId;
                await Task.Delay((receiver.SessionLockedUntil - DateTime.UtcNow) + TimeSpan.FromSeconds(5));

                var secondMessage = await receiver.ReceiveMessageAsync();

                Assert.AreEqual(sessionId, receiver.SessionId);
                Assert.AreEqual(receiver.SessionId, secondMessage.SessionId);

                // Even though the receiver has re-established the session link, since the first message was
                // received before we reconnected, the message won't be able to be settled. This is analogous
                // to the case of reconnecting a regular non-session link and getting a MessageLockLost error.
                Assert.That(
                    async() => await receiver.CompleteMessageAsync(firstMessage),
                    Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)).EqualTo(ServiceBusFailureReason.SessionLockLost));
                await Task.Delay((receiver.SessionLockedUntil - DateTime.UtcNow) + TimeSpan.FromSeconds(5));

                // If another receiver accepts the session after the lock is lost, we expect a SessionCannotBeLocked error,
                // when we try to receive again with our initial receiver.
                ServiceBusSessionReceiver secondReceiver = await client.AcceptSessionAsync(
                    scope.QueueName,
                    sessionId);

                try
                {
                    await receiver.ReceiveMessageAsync();
                }
                catch (ServiceBusException ex) when(ex.Reason == ServiceBusFailureReason.SessionCannotBeLocked)
                {
                    return;
                }
                catch (Exception ex)
                {
                    Assert.Fail($"Expected exception not thrown: {ex}");
                }
                Assert.Fail("No exception thrown!");
            }
        }
Ejemplo n.º 24
0
        public AzureConsumerContext(IConsumerContext consumerContext, ProcessMessageEventArgs azureContext, IServiceBus bus, ServiceBusSender sender)
        {
            _consumerContext = consumerContext;
            _azureContext    = azureContext;
            _bus             = bus;
            _sender          = sender;

            if (_azureContext.Message.ApplicationProperties.TryGetValue(nameof(Redeliveries), out var raw))
            {
                if (raw is object && int.TryParse(raw.ToString(), out var i))
                {
                    Redeliveries += i + 1;
                }
            }
            Redeliveries += _consumerContext.Redeliveries;
        }
Ejemplo n.º 25
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.CreateBatchAsync();

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

                await sender.SendBatchAsync(batch);

                var topicName        = scope.TopicName;
                var subscriptionName = scope.SubscriptionNames.First();

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

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

                while (remainingMessages > 0)
                {
                    foreach (var item in await receiver.ReceiveBatchAsync(remainingMessages))
                    {
                        remainingMessages--;
                        messageEnum.MoveNext();
                        Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId);
                        Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId);
                        var props = new Dictionary <string, object>();
                        // these should be ignored by DeadLetter property getters as they are not strings
                        props[ServiceBusReceivedMessage.DeadLetterReasonHeader]           = DateTime.UtcNow;
                        props[ServiceBusReceivedMessage.DeadLetterErrorDescriptionHeader] = DateTime.UtcNow;

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

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

                messageEnum.Reset();
                remainingMessages = messageCount;
                var deadLetterReceiver = client.CreateDeadLetterReceiver(topicName, subscriptionName);

                while (remainingMessages > 0)
                {
                    foreach (var msg in await deadLetterReceiver.ReceiveBatchAsync(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.Properties[ServiceBusReceivedMessage.DeadLetterReasonHeader]);
                        Assert.IsNotNull(msg.Properties[ServiceBusReceivedMessage.DeadLetterErrorDescriptionHeader]);
                        await deadLetterReceiver.CompleteAsync(msg.LockToken);
                    }
                }
                Assert.AreEqual(0, remainingMessages);

                var deadLetterMessage = await deadLetterReceiver.PeekAsync();

                Assert.IsNull(deadLetterMessage);
            }
        }
Ejemplo n.º 26
0
        public async Task MaxAutoLockRenewalDurationRespected(int numThreads, int autoLockRenewalDuration)
        {
            var lockDuration = ShortLockDuration;

            await using (var scope = await ServiceBusScope.CreateWithQueue(
                             enablePartitioning: false,
                             enableSession: false,
                             lockDuration: lockDuration))
            {
                await using var client = CreateClient();
                ServiceBusSender sender = client.CreateSender(scope.QueueName);

                using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync();

                var messageSendCt = numThreads;
                ServiceBusMessageBatch messageBatch = ServiceBusTestUtilities.AddMessages(batch, messageSendCt);

                await sender.SendMessagesAsync(messageBatch);

                var options = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls         = numThreads,
                    AutoCompleteMessages       = false,
                    MaxAutoLockRenewalDuration = TimeSpan.FromSeconds(autoLockRenewalDuration)
                };
                await using 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   += ServiceBusTestUtilities.ExceptionHandler;
                await processor.StartProcessingAsync();

                async Task ProcessMessage(ProcessMessageEventArgs args)
                {
                    var message = args.Message;
                    // wait until 5 seconds past the locked until time
                    await Task.Delay(message.LockedUntil.Subtract(DateTimeOffset.UtcNow).Add(TimeSpan.FromSeconds(5)));

                    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);
                        ServiceBusException exception = await AsyncAssert.ThrowsAsync <ServiceBusException>(
                            async() => await args.CompleteMessageAsync(message, args.CancellationToken));

                        Assert.AreEqual(ServiceBusFailureReason.MessageLockLost, exception.Reason);
                        Interlocked.Increment(ref messageCt);
                        var setIndex = Interlocked.Increment(ref completionSourceIndex);
                        if (setIndex < numThreads)
                        {
                            completionSources[setIndex].SetResult(true);
                        }
                    }
                }

                await Task.WhenAll(completionSources.Select(source => source.Task));

                await processor.StopProcessingAsync();

                // greater or equal because the same message may be received multiple times
                Assert.GreaterOrEqual(messageCt, numThreads);
            }
        }
Ejemplo n.º 27
0
        public async Task LogsEvents()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
                await using var client = GetNoRetryClient();
                _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 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);

                #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 using an implicit cast
                    string body = receivedMessage.Body.ToString();
                }
            }
        }
Ejemplo n.º 29
0
        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 = CreateClient();
                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,
                    AutoCompleteMessages = false
                };
                await using 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 != ServiceBusFailureReason.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);
            }
        }
Ejemplo n.º 30
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);

                // create the sender
                ServiceBusSender sender = client.CreateSender(queueName);

                // create a set of messages that we can send
                ServiceBusMessage[] messages = new ServiceBusMessage[]
                {
                    new ServiceBusMessage("First"),
                    new ServiceBusMessage("Second")
                };

                // send the message batch
                await sender.SendMessagesAsync(messages);

                #region Snippet:ServiceBusConfigureProcessor
                // create the options to use for configuring the processor
                var options = new ServiceBusProcessorOptions
                {
                    // By default or when AutoCompleteMessages is set to true, the processor will complete the message after executing the message handler
                    // Set AutoCompleteMessages to false to [settle messages](https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock) on your own.
                    // In both cases, if the message handler throws an exception without settling the message, the processor will abandon the message.
                    AutoCompleteMessages = false,

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

                // create a processor that we can use to process the messages
                await using ServiceBusProcessor processor = client.CreateProcessor(queueName, options);

                // configure the message and error handler to use
                processor.ProcessMessageAsync += MessageHandler;
                processor.ProcessErrorAsync   += ErrorHandler;

                async Task MessageHandler(ProcessMessageEventArgs args)
                {
                    string body = args.Message.Body.ToString();

                    Console.WriteLine(body);

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

                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);
                }

                // start processing
                await processor.StartProcessingAsync();

                // since the processing happens in the background, we add a Conole.ReadKey to allow the processing to continue until a key is pressed.
                Console.ReadKey();
                #endregion
                #endregion
            }
        }