As organizations continually struggle to make sense of the growing amounts of data available, they increasingly rely on their IT teams to unlock the value of that data. To achieve this, IT teams need to build scalable web applications faster and with the ability to react in real-time. In response to this growing need, Microsoft has released an extension of Azure Functions called Durable Functions. While Durable Functions still provides a server-less, cost saving solution, it also provides significantly more features. One feature of particular interest is Async HTTP APIs, which can be used to handle long running tasks in the back end.
The importance of this new feature for NLogic is its ability to help reduce the cost of the infrastructure, like Azure hosted services. It allows us to build web applications faster while writing less code.
The following looks specifically at one of the most time consuming development tasks: handling Azure Web App long running processes.
Design overview
Let’s say we have a web application submitting data to a web API server to process via an AJAX call. To complete the request, the server needs to call an external API (e.g. GitHub Server) which may take some time to finish.
To prevent the browser from timing out, the server will offload the job to a function and return a new Task ID for the client to start long (or short) polling*, while showing a busy spinner.
In our case, we aren’t going to expose the function directly to the client. We want our web server to handle the authentication/authorization part, keeping the function light.
*Note: Polling may add some overhead. If performance is a concern or notifications are time-sensitive, consider using Web Sockets/SignalR Service instead
Building Function App
The source code is available on GitHub.
First, we need to create a Durable Function app in Visual Studio as described in Create your first durable function in C#. We won’t be deploying our function to Azure, as running it locally is good enough for this example.
Next, we add a GitHub Client class (as Typed Client) and inject .NET HttpClient to generate HTTP requests.
To use GitHubClient in our app, we need to register it using Dependency Injection (yes, Azure Functions support DI).
For this, we first create a new class Startup derived from FunctionsStartup and override the Configure function. The GitHubClient functionality will be available via injection of IGitHubClient.
Using Polly , we instruct the function (by calling WaitAndRetryAsync) to wait 3 seconds and retry one more time in case of an HTTP error.
We used Polly as it has many helpful features and resilience policies. For example, Circuit-Breaker Policy can stop requests for 1 minute, after 3 consecutive failed attempts, to give the target system some time to recover.
Running on a Local Machine
Once the app is successfully built, here is how it will look when you start it
To trigger the function, open Postman and send HTTP POST http://localhost:7071/api/Orchestrator_HttpStart with input data in JSON format {"gitHubOrgName":"aspnet"}
Once triggered, the function returns HTTP Code 202 (Accepted), with the following data:
The id will be sent to the client to submit on each server poll request. StatusQueryGetUri can be used by our server to get the function’s status, and purgeHistoryDeleteUri is called to clean up the allocated resources once the execution is done.
For example, if we click on statusQueryGetUri and send a GET request while the function is executing (not completed), we will get HTTP Code 202. Once the function’s execution is completed, the result is HTTP Code 200. Note that the output is the actual result returned by the function.
Running on Azure
Ready to deploy your function to Azure? Here are a few things to consider.
- Access to the function is secured by a Function key. The key should be included in the request URL (Query Parameter named “code”). To get the full URL, go to “Function App/Functions/Orchestrator_HttpStart/Code + Test/Get Function URL”
- App Settings stored in local.settings.json are not published to Azure. You need to add them manually by going to “Function App/Configuration/App Settings".
Conclusion
At this point, your web application should be set up to manage more calls, without any downtime, and be able to provide your business unit with real-time access to the data.
Thank you for reading and Happy Coding.
Other blog posts you may enjoy
5 ways to build application flexibility and efficiency
A comparison of Newtonsoft.Json and System.Text.Json