Exemple #1
0
        static async Task MainAsync()
        {
            serviceBusClient    = new ServiceBusClient(ServiceBusConnectionString);
            serviceBusProcessor = serviceBusClient.CreateProcessor(TopicName, SubscriptionName, RegisterOptions());
            //serviceBusProcessor = serviceBusClient.CreateProcessor(QueueName, RegisterOptions());
            serviceBusProcessor.ProcessErrorAsync   += ExceptionReceivedHandler;
            serviceBusProcessor.ProcessMessageAsync += ProcessMessagesAsync;



            Console.WriteLine("======================================================");
            Console.WriteLine("Press ENTER key to exit after receiving all the messages.");
            Console.WriteLine("======================================================");

            // Register the queue message handler and receive messages in a loop
            try
            {
                serviceBusProcessor.StartProcessingAsync();
            }
            catch (ServiceBusException e)
            {
                System.Console.WriteLine("OH SNAP!: " + e.Message);
            }


            Console.ReadLine();
            await serviceBusProcessor.StopProcessingAsync();

            await serviceBusProcessor.CloseAsync();

            await serviceBusClient.DisposeAsync();
        }
        static async Task ReceiveSalesMessageAsync()
        {
            Console.WriteLine("======================================================");
            Console.WriteLine("Press ENTER key to exit after receiving all the messages.");
            Console.WriteLine("======================================================");


            var client = new ServiceBusClient(ServiceBusConnectionString);

            var processorOptions = new ServiceBusProcessorOptions
            {
                MaxConcurrentCalls   = 1,
                AutoCompleteMessages = false
            };

            await using ServiceBusProcessor processor = client.CreateProcessor(QueueName, processorOptions);

            processor.ProcessMessageAsync += MessageHandler;
            processor.ProcessErrorAsync   += ErrorHandler;


            await processor.StartProcessingAsync();

            Console.Read();

            await processor.CloseAsync();
        }
Exemple #3
0
        private async Task CloseMessageReceiverAsync()
        {
            if (_messageProcessor is null)
            {
                return;
            }

            try
            {
                Logger.LogTrace("Closing message pump '{JobId}' on entity path '{EntityPath}' in '{Namespace}'", JobId, EntityPath, Namespace);
                await _messageProcessor.StopProcessingAsync();

                _messageProcessor.ProcessMessageAsync -= ProcessMessageAsync;
                _messageProcessor.ProcessErrorAsync   -= ProcessErrorAsync;
                await _messageProcessor.CloseAsync();

                Logger.LogInformation("Message pump '{JobId}' on entity path '{EntityPath}' in '{Namespace}' closed : {Time}", JobId, EntityPath, Namespace, DateTimeOffset.UtcNow);
            }
            catch (TaskCanceledException)
            {
                // Ignore.
            }
            catch (Exception exception)
            {
                Logger.LogWarning(exception, "Cannot correctly close the message pump '{JobId}' on entity path '{EntityPath}' in '{Namespace}': {Message}", JobId, EntityPath, Namespace, exception.Message);
            }
        }
Exemple #4
0
        private static Task ReceiveMessages(string queueName, CancellationToken cancellationToken)
        {
            var doneReceiving             = new TaskCompletionSource <bool>();
            ServiceBusProcessor processor = _client.CreateProcessor(queueName);

            // close the receiver and factory when the CancellationToken fires
            cancellationToken.Register(
                async() =>
            {
                await processor.CloseAsync();
                doneReceiving.SetResult(true);
            });

            processor.ProcessMessageAsync += async args =>
            {
                ServiceBusReceivedMessage message = args.Message;
                // If the message holds JSON data and the label is set to "Scientist",
                // we accept the message and print it.
                if (message.Subject != null &&
                    message.ContentType != null &&
                    message.Subject.Equals("Scientist", StringComparison.InvariantCultureIgnoreCase) &&
                    message.ContentType.Equals("application/json", StringComparison.InvariantCultureIgnoreCase))
                {
                    var body = message.Body;

                    // System.Text.JSON does not currently support deserializing to dynamic
                    Dictionary <string, string> scientist = body.ToObjectFromJson <Dictionary <string, string> >();

                    lock (Console.Out)
                    {
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Console.WriteLine(
                            "\t\t\t\tMessage received: \n\t\t\t\t\t\tMessageId = {0}, \n\t\t\t\t\t\tSequenceNumber = {1}," +
                            " \n\t\t\t\t\t\tEnqueuedTime = {2}," + "\n\t\t\t\t\t\tExpiresAt = {4}, \n\t\t\t\t\t\tContentType = \"{3}\"," +
                            " \n\t\t\t\t\t\tContent: [ firstName = {5}, name = {6} ]",
                            message.MessageId,
                            message.SequenceNumber,
                            message.EnqueuedTime,
                            message.ContentType,
                            message.ExpiresAt,
                            scientist["firstName"],
                            scientist["name"]);
                        Console.ResetColor();
                    }

                    await args.CompleteMessageAsync(message, args.CancellationToken);
                }
                else
                {
                    // if the messages doesn't fit the criteria above, we deadletter it
                    await args.DeadLetterMessageAsync(message, cancellationToken : args.CancellationToken);
                }
            };

            processor.ProcessErrorAsync += LogMessageHandlerException;
            _ = processor.StartProcessingAsync(cancellationToken);
            return(doneReceiving.Task);
        }
        public async Task OnMessageExceptionHandlerCalled()
        {
            var invalidQueueName = "nonexistentqueuename";
            var exceptionReceivedHandlerCalled = false;

            await using var client = CreateClient();
            ServiceBusProcessor         processor            = client.CreateProcessor(invalidQueueName);
            TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            processor.ProcessMessageAsync += ProcessMessage;
            processor.ProcessErrorAsync   += ProcessErrors;

            Task ProcessMessage(ProcessMessageEventArgs args)
            {
                Assert.Fail("Unexpected exception: Did not expect messages here");
                return(Task.CompletedTask);
            }

            Task ProcessErrors(ProcessErrorEventArgs args)
            {
                Assert.NotNull(args);
                Assert.NotNull(args.Exception);
                Assert.AreEqual(processor.FullyQualifiedNamespace, args.FullyQualifiedNamespace);
                Assert.AreEqual(ServiceBusErrorSource.Receive, args.ErrorSource);
                Assert.AreEqual(processor.EntityPath, args.EntityPath);

                if (args.Exception is ServiceBusException sbException)
                {
                    if (sbException.Reason == ServiceBusFailureReason.MessagingEntityNotFound ||
                        // There is a race condition wherein the service closes the connection when getting
                        // the request for the non-existent queue. If the connection is closed by the time
                        // our exception handling kicks in, we throw it as a ServiceCommunicationProblem
                        // as we cannot be sure the error wasn't due to the connection being closed,
                        // as opposed to what we know is the true cause in this case,
                        // MessagingEntityNotFound.
                        sbException.Reason == ServiceBusFailureReason.ServiceCommunicationProblem)
                    {
                        exceptionReceivedHandlerCalled = true;
                        taskCompletionSource.SetResult(true);
                        return(Task.CompletedTask);
                    }
                }

                Assert.Fail($"Unexpected exception: {args.Exception}");
                return(Task.CompletedTask);
            }

            await processor.StartProcessingAsync();

            await taskCompletionSource.Task;

            Assert.True(exceptionReceivedHandlerCalled);
            await processor.CloseAsync();

            Assert.That(
                async() => await processor.StartProcessingAsync(),
                Throws.InstanceOf <ObjectDisposedException>());
        }
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            _cancellationToken = cancellationToken;
            _client            = await _clientFactory.GetReceiverClient <T>(new ServiceBusProcessorOptions
            {
                AutoCompleteMessages       = false,
                MaxAutoLockRenewalDuration = Settings.MessageLockTimeout,
                MaxConcurrentCalls         = Settings.MaxConcurrentCalls,
                PrefetchCount = Settings.PrefetchCount,
                ReceiveMode   = ServiceBusReceiveMode.PeekLock
            }).ConfigureAwait(false);

            var queueName = AutoMessageMapper.GetQueueName <T>();

            if (!await _managementClient.QueueExistsAsync(queueName, _cancellationToken).ConfigureAwait(false))
            {
                try
                {
                    var serviceBusCreationOptions = GetServiceBusCreationOptions();

                    await _managementClient.CreateQueueAsync(new CreateQueueOptions(queueName)
                    {
                        EnablePartitioning      = serviceBusCreationOptions.EnablePartitioning,
                        EnableBatchedOperations = serviceBusCreationOptions.EnableBatchedOperations
                    }, cancellationToken).ConfigureAwait(false);
                }
                catch (ServiceBusException e)
                {
                    _log.Error(e, "Failed to create queue {QueueName}", queueName);
                    throw;
                }
            }
            _deadLetterLimit = Settings.DeadLetterDeliveryLimit;

            _client.ProcessMessageAsync += ClientOnProcessMessageAsync;
            _client.ProcessErrorAsync   += ClientOnProcessErrorAsync;

            await _client.StartProcessingAsync(cancellationToken);

#pragma warning disable 4014
            // ReSharper disable once MethodSupportsCancellation
            Task.Run(async() =>
            {
                _cancellationToken.WaitHandle.WaitOne();
                //Cancellation requested
                try
                {
                    _log.Information($"Closing ServiceBus channel receiver for {typeof(T).Name}");
                    await _client.CloseAsync(CancellationToken.None);
                }
                catch (Exception)
                {
                    //Swallow
                }
            });
#pragma warning restore 4014
        }
        private Task ErrorHandlerAsync(ProcessErrorEventArgs arg)
        {
            _logger.LogError(arg.Exception, "Message handler encountered an exception");
            _logger.LogDebug($"- Error Source: {arg.ErrorSource}");
            _logger.LogDebug($"- Fully Qualified Namespace: {arg.FullyQualifiedNamespace}");
            _logger.LogDebug($"- Entity Path: {arg.EntityPath}");
            _logger.LogDebug($"- Exception: {arg.Exception.ToString()}");

            return(_serviceBusProcessor.CloseAsync());
        }
    public async Task CloseConnectionAsync()
    {
        await _serviceBusProcessor.StopProcessingAsync();

        await _serviceBusProcessor.CloseAsync();

        await _serviceBusClient.DisposeAsync();

        Console.WriteLine("Client connection closed");
    }
        //ServiceBusProcessor.StopProcessingAsync currently has a bug when using the AMQP protocol that prevents it from gracefully shutting down in a timely manner
        //it will timeout after 1 min and eventually shutdown but we don't want to wait for that so do all shutdown waiting in an async void method.
        private async void Stop()
        {
            await using (_sender)
                await using (_processor)
                {
                    await _processor.StopProcessingAsync();

                    await _processor.CloseAsync();

                    await _sender.CloseAsync();
                }
        }
Exemple #10
0
        private static Task PickUpAndFixDeadletters(string queueName, ServiceBusSender resubmitSender, CancellationToken cancellationToken)
        {
            var doneReceiving = new TaskCompletionSource <bool>();

            // here, we create a receiver on the Deadletter queue
            ServiceBusProcessor dlqProcessor =
                _client.CreateProcessor(queueName, new ServiceBusProcessorOptions {
                SubQueue = SubQueue.DeadLetter
            });

            // close the receiver and factory when the CancellationToken fires
            cancellationToken.Register(
                async() =>
            {
                await dlqProcessor.CloseAsync();
                doneReceiving.SetResult(true);
            });

            // register the RegisterMessageHandler callback
            dlqProcessor.ProcessMessageAsync += async args =>
            {
                // first, we create a new sendable message of the picked up message
                // that we can resubmit.
                var resubmitMessage = new ServiceBusMessage(args.Message);
                // if the message has an "error" we know the main loop
                // can't handle, let's fix the message
                if (resubmitMessage.Subject != null && resubmitMessage.Subject.Equals("Physicist"))
                {
                    lock (Console.Out)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine(
                            "\t\tFixing: \n\t\t\tMessageId = {0}, \n\t\t\tSequenceNumber = {1}, \n\t\t\tLabel = {2}",
                            args.Message.MessageId,
                            args.Message.SequenceNumber,
                            args.Message.Subject);
                        Console.ResetColor();
                    }

                    // set the label to "Scientist"
                    resubmitMessage.Subject = "Scientist";
                    // and re-enqueue the cloned message
                    await resubmitSender.SendMessageAsync(resubmitMessage);
                }

                // finally complete the original message and remove it from the DLQ
                await args.CompleteMessageAsync(args.Message);
            };
            dlqProcessor.ProcessErrorAsync += LogMessageHandlerException;
            _ = dlqProcessor.StartProcessingAsync();
            return(doneReceiving.Task);
        }
Exemple #11
0
        public async Task CanDisposeClosedProcessor()
        {
            var processor = new ServiceBusProcessor(
                GetMockedReceiverConnection(),
                "entityPath",
                false,
                new ServiceBusProcessorOptions());

            processor.ProcessMessageAsync += _ => Task.CompletedTask;
            processor.ProcessErrorAsync   += _ => Task.CompletedTask;
            await processor.StartProcessingAsync().ConfigureAwait(false);

            await processor.CloseAsync();

            await processor.DisposeAsync();
        }
Exemple #12
0
 public void Dispose()
 {
     _subsManager.Clear();
     _processor.CloseAsync().GetAwaiter().GetResult();
 }
 public async ValueTask DisposeAsync()
 {
     _subsManager.Clear();
     await _processor.CloseAsync();
 }