Async Http APIs with Azure Durable Functions (and Polling Client)
Introduction
Azure Durable Functions have support for different patterns, which enable us to build serverless and stateful applications without worrying about the state management implementation details. One of these useful pattern is the Asynchronous Http APIs. This pattern comes in handy when client applications need to trigger long running processes exposed as APIs and do something else after a status is reached. You might be thinking that the best way to implement an async API is by enabling the API to raise an event once it finishes so the client can react to it. For instance via a webhook (Http callback request), an Event Grid event, or even using SignalR. That is true, however, in many cases, client apps cannot be modified, or there are security or networking restrictions which make polling the best or the only feasible alternative. In this post, I’ll describe how to implement the Asynchronous Http API pattern on Durable Functions based on the polling approach.
Before we get into the details, it’s worth noting that this pattern can be used to implement a custom trigger or action for Logic Apps with the polling pattern.
Scenario
To demonstrate how to implement this pattern, I’ll use the scenario of “Call for Speakers” in a conference. In this, potential speakers submit a topic through an app, and they are very keen to know as soon as possible if they have been selected to present. Of course, in a real scenario there will be timelines and speakers would be notified before the agenda is published, so they wouldn’t need to keep continuously asking for the status of their submission. But I believe you get the idea that this is being used for illustration purposes only ;)
Solution Overview
The solution is based on Azure Durable Functions’ building blocks, including orchestration clients, the orchestration function, and activity functions. I’ve used dummy activity function, as the main purpose of this post is to demonstrate the capabilities to implement an Asynchronous Http API. In case you want to understand how to implement this further, you can have a look at my previous post on how to implement an approval workflows on Durable Functions.
The diagram below shows the different components of the solution.
Solution and Components
The main components of the solution are described below. The comments in the code should also help you to better understand each of them. You can find the full solution sample code here.
Submit Function
Http triggered function which implements the DurableOrchestrationClient
. This function receives a “Call-for-Speakers” submission as a POST with a JSON payload as the request body. Then, it starts the submission processing orchestration. Finally, it returns to the client the URL to the endpoint to get the status using the location
and retry-after
http headers.
ProcessSubmission Function
Orchestration function which implements the function chaining pattern for each of the stages of the submission process. It’s also in charge of updating the custom status of the instance as it progresses.
Get Status Function
This is an Http function that allows clients to get the status of an instance of a Durable Function orchestration. You can get more details of this implementation here.
In many of the samples, they explain you how to use the CreateCheckStatusResponse
method to generate the response to the client. However, make sure that that you fully understand what this returns. Given that the return payload includes management endpoints with their corresponding keys, by providing that, you would allow the clients not only to get the status of a running instance, but also to 1) get the activity execution history, 2) get the outputs of the already executed activity functions, 3) send external events to the orchestration instance, and 4) terminate that instance. If you don’t want to give those privileges to the clients, you need to expose an http function that handles that response and returns only the minimum information required. In this wrapper, you could also enrich the response if need be. If you only need to send back the status, I would recommend you to use the GetStatusAsync
method instead.
The sample function below makes use of the GetStatusAsync
method of the orchestration client, and leverages the location
and retry-after
Http headers.
Wrapping Up
In this post, I’ve shown how to implement Asynchronous Http APIs using Durable Functions with the polling consumer pattern. I’ve also explain the differences between using CreateCheckStatusResponse
and GetStatusAsync
methods. The former prepares a response which expose different management endpoints with a key that allow clients to do much more than just getting the status, while the latter just returns the instance status. I hope you’ve enjoyed and found useful this post.
If you are interested in more posts about patterns on Durable Functions, you can also check out:
- Azure Durable Functions Pattern: Approval Workflow with SendGrid
- Azure Durable Functions Pattern: Approval Workflow with Slack
Happy clouding!
Cross-posted on Deloitte Engineering
Follow me on @pacodelacruz