TheBoubou
TheBoubou

Reputation: 19933

Web API does not start when consume Azure queue

When I use the code below, the Web API does not start, I don't see the swagger page. Do you have an idea why ? Swagger starts normally when I comment the code in ConfigurationServices. I'd like have the normal behaviour (means see all endpoint from the controller) + subscribe a method to the queue.

public class Startup
{
    static QueueClient queueClient;

    public void ConfigureServices(IServiceCollection services)
    {
        try
        {
            queueClient = new QueueClient("BusConnectionString","QueueName");
            var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = 1,
                AutoComplete = false
            };
            queueClient.RegisterMessageHandler(ReceiveMessagesAsync, messageHandlerOptions);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            Console.ReadKey();
            queueClient.CloseAsync();
        }
    }

    static async Task ReceiveMessagesAsync(Message message, CancellationToken token)
    {
        Console.WriteLine($"Received message: {Encoding.UTF8.GetString(message.Body)}");

        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
    }

    static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
    {
        Console.WriteLine(exceptionReceivedEventArgs.Exception);
        return Task.CompletedTask;
    }
}

Below the code updated I hit the DoWork method every 5 seconds but I don't receive any message in ReceiveMessagesAsync and no exception

Update 1 :

public class TimedHostedService : IHostedService, IDisposable
{
    static QueueClient queueClient;

    Timer timer;

    readonly IConfiguration configuration;

    public TimedHostedService(IConfiguration configuration)
    {
        this.configuration = configuration;
    }

    public Task StartAsync(CancellationToken stoppingToken)
    {
        timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    void DoWork(object state)
    {
        try
        {
            queueClient = new QueueClient("QueueConnectionString", "QueueName"]);
            var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = 1,
                AutoComplete = false
            };
            queueClient.RegisterMessageHandler(ReceiveMessagesAsync, messageHandlerOptions);
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            queueClient.CloseAsync();
        }

    }

    public Task StopAsync(CancellationToken stoppingToken)
    {

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        timer?.Dispose();
    }

    static async Task ReceiveMessagesAsync(Message message, CancellationToken token)
    {
        Console.WriteLine($"Received message: {Encoding.UTF8.GetString(message.Body)}");

        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
    }

    static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
    {
        Console.WriteLine(exceptionReceivedEventArgs.Exception);
        return Task.CompletedTask;
    }

}

Upvotes: 0

Views: 190

Answers (1)

Peter Bons
Peter Bons

Reputation: 29840

You shouldn't do long running work in the startup phase. The initial code blocks executing by doing Console.ReadKey() in the startup phase.

Long running work should be done in the background.But not using a timer because now you spin up a new listener on every tick, and close it almost directly. Try this:

public class QueueProcessorService : IHostedService
{
    private QueueClient queueClient;
    
    public Task StartAsync(CancellationToken cancellationToken)
    {
        queueClient = new QueueClient("BusConnectionString", "QueueName");
        var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
        {
            MaxConcurrentCalls = 1,
            AutoComplete = false
        };
        queueClient.RegisterMessageHandler(ReceiveMessagesAsync, messageHandlerOptions);
        
        return Task.CompletedTask;
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        await queueClient.CloseAsync();
    }

    async Task ReceiveMessagesAsync(Message message, CancellationToken token)
    {
        Console.WriteLine($"Received message: {Encoding.UTF8.GetString(message.Body)}");

        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
    }

    Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
    {
        Console.WriteLine(exceptionReceivedEventArgs.Exception);
        return Task.CompletedTask;
    }
}

By the way, it seems like you are using a rather outdated package Microsoft.Azure.ServiceBus instead of the recommended one (Azure.Messaging.ServiceBus).

Upvotes: 1

Related Questions