Close

Durable Functions

I a previous post I explained the webhook solution to make it possible to call a long running function asynchronuously. This approach is quite complicated, since you will have to create and manage queues yourself. There’s a solution called Azure Durable Functions where you can simply call a function from your logic app an leave the heavy lifting to that very function. Conceptually it works as follows:

  1. Function A gets the request from Logic Apps
  2. Function A invokes a durable orchestrator function and returns the status (202 Accepted with location header for status updates)
  3. The durable orchestrator calls the function(s) that need to do work which may be > 2 minutes
  4. The Logic App will continue to check the location header (automatically) until a 200 status code is received.

When you look at the implementation, you will see three functions are created: a HttpTrigger function, a OrchestrationTrigger function and an ActivityTrigger function. A very good explanation can be found at the following link: Jeff Hollan on GitHub.

You will need to add the following NuGet packages to your Azure Function project:

  • Microsoft.Azure.WebJobs.Extensions.DurableTask, v1.5.0
  • Microsoft.Net.Sdk.Functions, v1.0.14

The DurableTask Extension can be added via the NuGet Package Manager (Tools menu). Command:
PM> Install-Package Microsoft.Azure.WebJobs.Extensions.DurableTask -Version 1.5.0

Important note: You need to understand the concept of task hubs. See Microsoft Docs. When you create multiple durable functions (linked to the same storage account), you will need a separate task hub per function. When no task hub is specified, the default task hub named durablefunctionshub is used. In Azure blob storage, you will see taskhub-leases in blob storage as well as queue entries. The task hub is automatically created in the storage account you specify in application setting AzureWebJobStorage and listens for asynchronuous response.

When testing your function in Visual Studio, the task hub is specified in local.settings.json:

{
“IsEncrypted”: false,

“durableTask”: {
“HubName”: “wcstaskhub”
},
“Values”: {
“APPINSIGHTS_INSTRUMENTATIONKEY”: “1ef50250-49f8-463d-849a-e264336c6797”,
“AzureWebJobsStorage”: “DefaultEndpointsProtocol=https;AccountName=bloasbdevst02;AccountKey=spgiGm…EndpointSuffix=core.windows.net”,

},
“ConnectionStrings”: {
“OutputDataConnectionString”: “Server=tcp:blo-asb-dev.database.windows.net,1433;Initial Catalog=db-blo-asb-dev-sql…”
}
}

When deploying to Azure, specify the task hub in the host.json file:

{
“durableTask”: {
“HubName”: “wcstaskhub”
},
“Values”: {
“APPINSIGHTS_INSTRUMENTATIONKEY”: “1ef50250-49f8-463d-849a-e264336c6797”,
“AzureWebJobsStorage”: “DefaultEndpointsProtocol=https;AccountName=bloasbdevst02;AccountKey=spgiGma5h1W7Pdey7NRGa/KOqCqjUROf7YNsEqoD4GiZ/NdTPezDQ3XTojBz2MI7P6zVBH+qEqIYFXwMC9VsFg==;EndpointSuffix=core.windows.net”,

}
}

The tradeoff to this approach is potential added latency. The polling pattern does mean there may be some delay between when the work is completed and when the response is returned to the logic app. That’s because you specify a polling interval in the parent HttpTrigger function.