GO TO:
Azure Functions
Azure Functions is a serverless option that reduces the need for extensive coding, enabling you to utilize minimal infrastructure and ultimately reduce expenses. The cloud infrastructure supplies all the necessary resources to sustain your applications, eliminating the need to concern yourself with deployments and server maintenance.
Azure Durable Functions – what is it?
Usually, the system we develop isn’t just “a set of functionalities or modules” (Function-as-a-Service), but rather “a set of multiple functionalities and modules influencing one another, dependent and interacting”. Thanks to the Azure Durable Functions, we are able to master this process. Azure Durable Function is the orchestrator controlling the entire business process, meaning our workflow. Durable Function is an extension of Azure Functions which allows you to optimize processes in a serverless environment. Read on to find out more about durable functions in a serverless environment.
Durable Function is an extension of Azure Functions which allows you to optimize processes in a serverless environment. With Azure Durable Functions, you can create stateful workflows that can span a longer period of time or can be triggered by external events. This means that developers can build complex, long-running processes that are resilient to failures and can automatically recover from where they left off. Azure Durable Functions also provide built-in support for monitoring and managing the workflow state, making it easier to debug and troubleshoot issues.
With Azure Durable Functions, you can create stateful workflows that can span a longer period of time or can be triggered by external events, allowing developers to build complex, long-running processes that are resilient to failures. This approach is complemented by reactive programming principles, which you can explore in depth with RxJS, a powerful library for handling asynchronous data streams. To gain a deeper understanding of how reactive programming can enhance your serverless applications, explore reactive programming with RxJS.
Azure Storage
To operate, Durable Functions extension requires a storage provider. Azure Storage is the most cost-effective and convenient choice as it does not require any extra setup. While it is the default option, it does have some restrictions, such as limits on transaction frequency and data sizes for queue messages and Azure Table entities.
Creating Azure Durable Functions
To develop Durable Functions in the Azure portal, the first step is to download the installation package. The Durable Functions extension enables you to use any programming language supported by the Azure Functions service. These can be found on the official Azure portal page. Later in the article, I will demonstrate how to use Durable Functions in real-world scenarios.
What does Microsoft Azure Durable Functions consist of?
Azure Durable Functions consist of 3 basic types of blocks:
Client Function
A kind of starter that gets the process up and running. It is most often triggered by an http request, adding a record to the database, uploading a file, etc.
Orchestrator Function
The process that controls our workflow – this is where we set up the sequence of steps in the process.
Activity Function
A specific functionality, e.g. retrieving a record from a database, sending an e-mail, issuing an invoice, etc.
Read also:
Let’s explore Azure Durable Functions in practice
For the purposes of the article, let’s assume that we run a web fashion store, and after the payment has been credited, we want to present the customer with possible color versions and, once the decision has been made, close the order. The initial process would look like this:
Understanding the process and concept of Durable Functions
Now let’s try to answer the following questions:
- How can we monitor what stage of the process the client is at?
- How can we spot any errors?
- Can we retry the step in the event of an error?
- Can we parallelize the steps?
- How can we receive confirmation of the event, i.e. the customer’s choice?
As you can see, there are a number of problems. The process is not perfect and cannot be easily controlled. Let’s get started and make sure it’s done right!
We begin with the ‘starter’:
[FunctionName("OrderStarter")] public static async Task<IActionResult> HttpStart( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req, [DurableClient] IDurableOrchestrationClient starter, ILogger log) { log.LogInformation("Received a payment"); string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); var order = JsonConvert.DeserializeObject<Order>(requestBody); // Function input comes from the request content. string instanceId = await starter.StartNewAsync("OrderOrchestrator", order); log.LogInformation($"Started orchestration with ID = '{instanceId}'."); return starter.CreateCheckStatusResponse(req, instanceId); }
We have created a function that is triggered by an http request and receives information about the order. Its key element is the type object IDurableOrchestrationClient, which starts the selected process.
Azure Durable Functions orchestration
In its initial, simplified form, it might just look like this:
[FunctionName("OrderOrchestrator")] public static async Task OrderOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context,ILogger log) { var order = context.GetInput<Order>(); { await context.CallActivityAsync<string>("PostThePayment", order); await context.CallActivityAsync<string>("GenerateColors", order); await context.CallActivityAsync<string>("SendNotification", order); await context.CallActivityAsync<string>("CloseOrderProcess", order); log.LogInformation($"Order processed successfully."); } }
As you can see, it’s a place from which we can control the entire ordering process.
To put it very simply, without diving into too much detail, the individual steps of the process, i.e. the Activity Function, can look like this:
[FunctionName("PostThePayment")] public static Task PostThePayment([ActivityTrigger] Order order, ILogger log) { log.LogInformation($"Do some stuff with order."); }
Let’s make modifications to find clear answers to the questions previously asked:
[FunctionName("OrderOrchestrator")] public static async Task OrderOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var color = new List<string>() { "white", "black", "pink", "green" }; var order = context.GetInput<Order>(); try { await context.CallActivityWithRetryAsync<string>( "PostThePayment", new RetryOptions(TimeSpan.FromSeconds(5),3), order); var tasks = new list<Task<string>>(); foreach (var color in colors) { var task = context.CallActivityAsync<string>("GenerateColors", order); } var generatedColors = await Task.WhenAll(tasks); await context.CallActivityAsync<string>("SendNotification", order); var userDecisionResult = await context.WaitForExternalEvent<string>("Approval", TimeSpan.FromHours(24)); if (userDecisionResult == null) { //time out - user not approved his choice in 24 hours //cancel order } if (userDecisionResult == "approved") { //do some activity when user approves his choice } await context.CallActivityAsync<string>("CloseOrderProcess", order); log.LogiInformation($"Order processed successfully."); } catch (Exception e) { //log exception, do some necessary cleanup } }
Now we can see the significant changes:
- By using the method CallActivityWithRetryAsync we are able to repeat the step in case of an error.
- Thanks to using the Fan-out Fan-in pattern, we made it possible to generate color versions much faster by parallelizing the processes.
- As you can see, through orchestration, we can easily use the construction Task. WhenAll to achieve the above goal.
- By using the pattern Human Interaction we have managed to simulate the system waiting for user confirmation within a given period of 24 hours.
The last question is: how do we monitor the state of the process? By default, after starting the orchestrator, we get a set of links to the list of workflow operations:
[FunctionName("ConfirmUserChoice")] public static async Task ConfirmUserChoice( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req, [DurableClient] IDurableOrchestrationClient client, ILogger log) { string result = req.GetQueryParameterDictionary()["result"]; string orderId = ""; //get orderId from db or other storage await client.RaiseEventAsync(orderId, "Approval", result);
So to monitor the current status of the process, just call statusQueryGetUri and as a result, you will get, for example:
{ • id: "35e9c2d4b7914d34a8c79e171587406f", • statusQueryGetUri: "http://localhost:7071/runtime/webhooks/durabletask/instances/35e9c2d4b7914d34a8c79e171587406f?taskHub=TestHubName&connection=Storage&code=i0BkAM8H9xo64Lve9oYAJvBstz7vzobVSHCKsKziaYXdXe4YCEhz0g==", • sendEventPostUri: "http://localhost:7071/runtime/webhooks/durabletask/instances/35e9c2d4b7914d34a8c79e171587406f/raiseEvent/{eventName}?taskHub=TestHubName&connection=Storage&code=i0BkAM8H9xo64Lve9oYAJvBstz7vzobVSHCKsKziaYXdXe4YCEhz0g==", • terminatePostUri: "http://localhost:7071/runtime/webhooks/durabletask/instances/35e9c2d4b7914d34a8c79e171587406f/terminate?reason={text}&taskHub=TestHubName&connection=Storage&code=i0BkAM8H9xo64Lve9oYAJvBstz7vzobVSHCKsKziaYXdXe4YCEhz0g==", • purgeHistoryDeleteUri: "http://localhost:7071/runtime/webhooks/durabletask/instances/35e9c2d4b7914d34a8c79e171587406f?taskHub=TestHubName&connection=Storage&code=i0BkAM8H9xo64Lve9oYAJvBstz7vzobVSHCKsKziaYXdXe4YCEhz0g==", • }
We see that the process is now over and it can be considered completed.
Benefits of Durable Functions
- Durable Functions are based on Microsoft Azure – a platform that is used by hundreds of thousands of people on a daily basis.
- Azure Durable Function can work in serverless mode, popularly known as pay-as-you-go – that is, you pay only for the time you use the service.
- You can scale it freely depending on the load. There is no need to implement or set anything. The function will scale to such an extent as to speed up the task execution as much as possible.
- Each functionality can be divided into separate, independently developed modules.
- You can write each functionality (function) using a given language, e.g. C #, Java, JavaScript, Python, etc.
- These functions can also be integrated with other Azure services, such as Azure Storage, Azure Event Grid, and Azure Service Bus, to create more complex and powerful workflows.
Overall, Azure Durable Functions provide developers with a flexible, scalable, and cost-effective solution for building and managing serverless workflows. By leveraging the power of Azure, developers can focus on writing code and creating efficient workflows without worrying about infrastructure and scaling challenges.
Azure Durable Function operates on a pay-as-you-go basis, where you only pay for the services you use. To ensure you are maximizing this benefit and not incurring unnecessary expenses, it’s crucial to understand how to optimize your Azure cloud costs. For a comprehensive guide on Azure cost management and optimization strategies, optimize your Azure cloud costs.
CLOUD ENGINEERING Make the best use of the cloud!Enter the digital world taking advantage of our cloud competences! Get started now! |
Durable Functions overview – summary
Using Azure serverless solutions lets you write stateful functions in a serverless environment. By building Durable Functions, you can freely create complicated workflows and fully control them. Native functions can work with the entire cloud ecosystem, so the possibilities of expansion are endless. What’s more, there is an option to use containers of functions in the on-premise environment – but that’s a matter for a separate article.
Using Azure serverless solutions allows you to write stateful functions in a serverless environment, offering immense possibilities for workflow optimization. In such scenarios, integrating Azure Active Directory for enhanced identity management becomes crucial. Azure Active Directory provides robust access and identity management capabilities, essential for multi-tenant applications and secure cloud interactions. To understand how Azure Active Directory can augment your serverless applications with superior security and user management features, integrate Azure Active Directory for enhanced identity management.
Find out more in Microsoft Learn: