Christian Vorhemus
Christian Vorhemus

Reputation: 2683

Make Azure Function run sequential on ServiceBusTrigger - maxConcurrentCalls not working

I have an Azure Function which looks like this

[FunctionName("Dispatcher")]
public static void Run([ServiceBusTrigger(queueName: "defaultqueue", Connection = "AzureWebJobsQueue")]string queueMessage, TraceWriter log)
{

    Dictionary<string, string> payload = JsonConvert.DeserializeObject<Dictionary<string, string>>(queueMessage);
    string url = payload["url"];

    try
    {
        log.Info("Collect result: " + url);

        using (HttpResponseMessage response = httpClient.GetAsync(url).Result)
        {
            int statusCode = (int)response.StatusCode;

            if (statusCode == 200)
            {
                var responseString = response.Content.ReadAsStringAsync().Result;
                DoStuff(log, responseString);
            }
        }
    }
}

The GET on the HttpClient takes roughly one minute. I want to wait for this call to finish until the next message is retrieved from the Service Bus Queue.

My host.json looks like this

{
    "functionTimeout": "23:00:00",
    "serviceBus": {
        "maxConcurrentCalls": 1,
        "prefetchCount": 1,
        "autoRenewTimeout": "00:05:00"
    }
}

However, when I put messages in the Service Bus Queue and run the Function, I instantly see multiple "Collect result: http://example.com" in the logs which apparently means, multiple instances of the Function are running in parallel. How can I configure Azure Functions to wait until HttpClient and DoStuff() is finished until pulling a new message from the Queue?

Upvotes: 3

Views: 3817

Answers (2)

Oliver
Oliver

Reputation: 9002

Anyone landing here using functions v2 - the host.json Service Bus binding configuration is different than in v1.

E.g.:

{
    "version": "2.0",
    "extensions": {
        "serviceBus": {
            "prefetchCount": 100,
            "messageHandlerOptions": {
                "autoComplete": true,
                "maxConcurrentCalls": 32,
                "maxAutoRenewDuration": "00:05:00"
            },
            "sessionHandlerOptions": {
                "autoComplete": false,
                "messageWaitTimeout": "00:00:30",
                "maxAutoRenewDuration": "00:55:00",
                "maxConcurrentSessions": 16
            }
        }
    }
}

Upvotes: 2

ElvisLives
ElvisLives

Reputation: 2275

I think you can still use the functionality that was ported from web jobs. In order to only execute the function once across all instances put this attribute above your method.

  [Singleton(Mode = SingletonMode.Listener)]

This isnt documented in the Functions sdk but it looks like its still there. Here is the webjobs documentation. Azure Web Jobs SDK Singleton

Upvotes: 4

Related Questions