Imagine you want to involve some long running custom external step in you Logic Apps workflow – this could be for example some step that requires manual work. There are two obvious ways to do this:
- Using a webhook action
- Using polling
In this post I’ll explore the second option, where I’ll implement an Azure Durable Function that completes only when a request is sent to a specific URL thus simulating a manual step that might take several days to complete.
Implementing Azure Durable Function
Let’s create a simple durable function that waits until another function gets called via a HTTP trigger. To start, add a durable function to you Azure Functions project in Visual Studio.
Now you have three methods visible that come with the durable function template. I’ve replaced the methods with the following three.
The first method is the actual function that initiates the durable process. It is a HTTP triggered function that has DurableOrchestrationClient starter object injected.
The method utilizes the starter object to
- start a new durable function, called DuraDemo1, and
- return HTTP 202 response via call to CreateCheckStatusResponse method.
The second line of the function body means, that whenever a HTTP GET/POST is received, a HTTP 202 response is sent back with Location header information indicating the URL which the caller can use to poll the status of the function execution.
For example Logic Apps and Flow know how to use this kind response – they will poll the Location URL until HTTP 200 OK is received.
The second method displayed below, is the one that the previous method initiated with the starter.StartNewAsync method. (This method is not called directly by clients)
The method is injected with the DurableOrchestrationContext object. The first line of the method body initiates a task to wait for an external event within the given orchestration context by calling WaitForExternalEvent template method. The first and only argument to the method is the event name that is waited for.
As you might guess, the third method is the one that fires the DuraDemoEvent event:
The method takes the durable function instance id as a route parameter. That instance id is used by the DurableOrchestrationClient object’s RaiseEventAsync method so that the runtime knows into which durable orchestration context to send the event to.
The above method would be called when the imaginary manual process completes (via a button click, for example). After the event is handled, the next polling call to the Location URL discussed earlier returns HTTP 200 OK like below.
Calling the long running process from Logic App workflow
The last part of this blog post is very straight forward. I created a simple Logic App workflow that makes a HTTP request to my DuraDemo1_HttpStart function (the function that returns 202 response and Location URL in the header).
When I run the workflow, the execution is stuck in the HTTP action – hence it is working as expected. Below I’ve waited for approximately seven minutes.
Now it’s time to call the DuraDemo1_SendEvent function so the workflow is allowed to continue. To do this, I need to find the durable orchestration context id from somewhere.
The context id can be found from the storage account that is attached to the function runtime. So I open up my storage explorer and browse to correct storage account and open up Tables. There you have two tables related to the durable functions context:
The one we’re interested in is DurableFunctionsHubInstances. It contains a row for each durable context, including the one that my Logic App workflow just started by calling the DuraDemo1_HttpStart function.
PartitionKey is the value we want. So, finally, I make a call
DuraDemo1_SendEvent passing the PartitionKey (= context id) to it. And voilá, the workflow finishes!