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(); }
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); } }
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(); } }
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); }
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(); }
public void Dispose() { _subsManager.Clear(); _processor.CloseAsync().GetAwaiter().GetResult(); }
public async ValueTask DisposeAsync() { _subsManager.Clear(); await _processor.CloseAsync(); }