How to exit application when C# ServiceBusClient can't connect to Service Bus

86 views Asked by At

When my .NET 7 worker service application can not connect to a service bus instance, I want it to error/exit. I see an error in the logs:

[ERR] ErrorHandler invoked with ErrorSource: Receive, FullyQualifiedNamespace: EntityPath, Exception: Azure.Messaging.ServiceBus.ServiceBusException: The requested name is valid, but no data o...

However, no exception is throw to my code, and it just keeps retrying this endlessly instead of exiting:

[WRN] RunOperation encountered an exception and will retry. Exception: Azure.Messaging.ServiceBus.ServiceBusException: The requested name is valid, but no data of the requested type was found. ErrorCode: NoData (ServiceCommunicationProblem).

I can not find where these logs come from, or intercept the exception, presumably from Azure.Messaging.ServiceBus

Question: how can I make my application throw an exception and exit when it can not connect to service bus / when the above happens?

Implementation details

In my application I configure a worker, and my ServiceBusClient in program.cs as follows:

services.AddHostedService<ServiceBusWorker>();
services.AddAzureClients(clientsBuilder =>
{
    clientsBuilder.AddServiceBusClient(serviceBusConfiguration?.ConnectionString)
      .WithName(serviceBusConfiguration?.MyQueue);
});

Then in my worker I construct as follows::

using Azure.Messaging.ServiceBus;

public ServiceBusWorker(IAzureClientFactory<ServiceBusClient> serviceBusClientFactory)
{
    _serviceBusClientFactory = serviceBusClientFactory;

    var connectionString = serviceBusConfiguration.Value.ConnectionString;

    _requestQueueClient = _serviceBusClientFactory.CreateClient(_requestQueue);

And the worker starts as follows:

public async Task StartAsync(CancellationToken cancellationToken)
{
    try
    {
        await using var requestProcessor = _requestQueueClient.CreateProcessor(_requestQueue, _serviceBusProcessorOptions);

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

        await requestProcessor.StartProcessingAsync(cancellationToken);

        while (!cancellationToken.IsCancellationRequested) { await Task.Delay(1000, cancellationToken); } //Need to improve. Required to keep the requestProcessor alive for now until better solution.
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error when starting the request processor");
        throw;
    }
}

What I tried

I have tried to configure a retry policy in program.cs as follows, but it doesn't make a difference, I assume because it relates to message retries and not my scenario:

services.AddAzureClients(clientsBuilder =>
{
    var serviceBusRetryOptions = new ServiceBusRetryOptions
    {
        MaxRetries = 3,
        Delay = TimeSpan.FromSeconds(2),
        TryTimeout = TimeSpan.FromSeconds(30)
    };

clientsBuilder
.AddServiceBusClient(serviceBusConfiguration?.ConnectionString)
.ConfigureOptions(options =>
    {
        options.RetryOptions = serviceBusRetryOptions;
    })
.WithName(serviceBusConfiguration?.RequestQueue);

clientsBuilder
.AddServiceBusClient(serviceBusConfiguration?.ConnectionString)
.ConfigureOptions(options =>
    {
        options.RetryOptions = serviceBusRetryOptions;
    })
.WithName(serviceBusConfiguration?.ResponseQueue);
});
1

There are 1 answers

1
jhmckimm On

You can inject IHostApplicationLifetime into your worker and call _hostApplicationLifetime.StopApplication() to stop your application gracefully.