Azure Duration Functions - How To Use And Implement It

Serverless architecture is one of the best approaches for any web-based application. It reduces many headaches related to the server's infrastructure and the cost. Using Azure Durable Functions, we can build a stateful application with the help of the stateless architecture in the cloud environment. In the case of Azure functions, we do not need to worry about deploying the applications and maintaining services because the cloud infrastructure provides us with all the resources required to run the application. Today, in this article, we will discuss the workflow process of the Azure Durable function and demonstrate how to implement the Azure Durable Function with the help of the Azure Portal. If anybody wants to know the overview of the Azure Durable Functions along with its application pattern, then read the below articles,

Design a Durable Function Work related to Employee Leave Approval Process

We can use the Azure Durable Functions to implement a long-running workflow as a combination of activities. During the workflow implementation, we need to map each process step as a function type and each task as an activity function. As the Azure Durable function is always an automated process, we do not need to worry about the monitoring or escalating related to a task that has not been completed. 

As per the example, we will discuss how we can implement the Employee Leave Approval process with the help of the Azure Durable Function workflow. So, in the process, we also need to consider those steps that may not be completed in time, and the process needs to be escalated. For example, what will happen if the Reporting Manager is not approved the application within the time? In this case, the process will automatically detect this step and escalate as mentioned in the workflow. In any business, escalation steps are always helpful as they help us define every task with a specific deadline to complete. This ensures the process that all the tasks are completed, not forgotten. In addition, in the escalation task, we can send reminders to the task's assignee or reassign the job to someone higher person per the organization hierarchy. 

In this section, we will design the Employee Leave Approval process workflow with the help of Durable Functions. In the process, our workflow will begin when an employee submits the leave application for approval. Then the application will be assigned as an approval task to the reporting manager. The reporting manager will either approve or reject the proposal. In the real environment, this event may also generate and send a notification (via email or SMS, or app-based message) to the employee to inform the outcome of the application. We will change the task's status to either approved or rejected in the demonstration. This workflow will contain the below steps,

  1. The employee submits a Leave Application.
  2. The approval task is assigned to the Reporting Manager so that they can review the Leave Application of the Employee.
  3. The Leave Application is either approved or rejected.
  4. An Escalation task is also allocated if the approval task is not completed within the pre-defined time limit.

The below Image demonstrates the visual representation of the workflow process,

The below tables list the workflow stepwise function types that we will use in the Durable Functions workflow,

Workflow Function Durable Function Type
Submitting a Leave Application for Approval Client Application Function
Assign the Approval Task to the relevant Reporting Manager Orchestration Function
Approval Task Activity Function
Escalation Task Activity Function

The Orchestration function will maintain the workflow rule that starts the escalation activity if the approval does not approve the application within the specified time. So, now as we finalize the workflow structure, we will write the code related to it in the next section.

Develop the Workflow-based Duration Functions

This section will demonstrate how to develop the workflow process to implement the scenario mentioned above using Azure Portal.

Step 1 - Create Function App

01. Sign in to the Azure Portal first and then click on Create a Resource option

02. In the left pane, select Compute, and select Function App under the Popular Product List. Then Create Function App Pane will open.

03. In the Basic Tab, provide the required field values like Resource Name, Function App Name, Run Time, Version, Etc.

04. Now click on the Review + Create Button and click on the Create button to create the Function App. Once we click on the create button, deployment of the Function is begun. It might take a few minutes to complete.

Step 2 - Install the required NPM Package

01. Using the JavaScript Durable Functions, we need to install some npm packages related to the durable functions. Once the Function App is created, navigate to the function app resource and App Service Editor under Development Tools and click on the Go Button.

02. In the left menu, select the WWWROOT folder and then click on the Open Console. We can use this console to access the webserver that hosts our functions and write the code for our functions.

03. Now create a new file called package.json and then open the file.

touch package.json
open package.json

04. Add the below-mentioned code within the file.

{
  "name": "azdemo-lmsapproval",
  "version": "1.0.0"
}

05. Return to the Azure Portal and select the Console option under the Development Tools. Once the console pane opens, run the below command – 

npm install durable-functions

06. Once the npm package installation is complete, click on the  Overview option and restart the function app so that it will take the effect of the installed packages.

Step 3 - Create Client Function to submit the Employee Leave Application

01. Now in the left pane of the Function App, click on the Functions under the Functions Section.

02. Now, click on the Create options.

03. In the Select Template list, find and select Durable Functions Http Starter. This template creates a durable function that runs in response to an HTTP Request.

04. In the Template Details, Provide the proper function name and in the Authorization level, choose the “Function” option and then click on the Create button. It will create the function.

05. Now, under the Developer part, select Code + Test option for this function.

06. The code for the index.json file will appear in the editor as below – 

const df = require("durable-functions");
module.exports = async function (context, req) {
    const client = df.getClient(context);
    const instanceId = await client.startNew(req.params.functionName, undefined, req.body);
    context.log(`Started orchestration with ID = '${instanceId}'.`);
    return client.createCheckStatusResponse(context.bindingData.req, instanceId);
};

Step 4 - Create Orchestrator Function

01. Now, again click the Functions section, and click on Create button to create the Orchestrator Function. 

02. Select the Durable Functions Orchestrator template from the list in the Create Function section.

03. Provide the function name as OrchtrstFunction and click on the create button.

04. Now open the newly created function in the code editor using the “Code + Test” option.

05. Replace the existing code with the below-mentioned code block and click on the Save button. 

const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
    const outputs = [];
    /*
    * We will call the approval activity with a reject and an approved to simulate both
    */
    outputs.push(yield context.df.callActivity("LeaveApproval", "Approved"));
    outputs.push(yield context.df.callActivity("LeaveApproval", "Rejected"));
    return outputs;
});

06. The code, as mentioned earlier called an Activity Function named LeaveApproval which we will create in the following steps. The orchestrator function will invoke the LeaveApproval function twice. The first time, it executes for accepting the proposal, and the second time tests for the application rejection logic.

Step 5 - Create the Activity Function

01. Now, again click the Functions section, and click on Create button to create the Activity Function. 

02. Select the Durable Functions Activity template from the list in the Create Function section.

03. Provide the function name as LeaveApproval and click on the create button.

04. Now open the newly created function in the code editor using the Code + Test option.

05. Replace the existing code with the below-mentioned code block and click on the Save button.

module.exports = async function (context) {
    return `Your Leave Application has been -  ${context.bindings.name}!`;
};

06. So, as per the process design, we have already developed the first three functions. Now, we need to test it. 

07. For this, select the HttpStart Function from the Function List, and it will navigate to the function pane.

08. Click on the Get Function Url option in the top bar and copy the URL. The Url will name like this – 

https://azdemo-lmsapproval.azurewebsites.net/api/orchestrators/{functionName}?code=vPkV3NANoBkGvAOEXPbe8VoXGejFWqf2e1XLCLvjfk3e74jy5IzyAw==

09. We need to replace the keyword {functionName} with the Orchestrator function name. In our case, the orchestrator function name is OrchtrstFunction. So the final URL after modification will be as below-

https://azdemo-lmsapproval.azurewebsites.net/api/orchestrators/OrchtrstFunction?code=vPkV3NANoBkGvAOEXPbe8VoXGejFWqf2e1XLCLvjfk3e74jy5IzyAw==

10. Open a new tab in the browser and paste the URL.

11. The response of the URL will be as below. But, first, we need to copy the statusQueryGetUri and paste it into the new browser tab.

12. The output of the statusQueryGetUri will be as below,

13. As per the structure of the orchestrator function, it calls two times and combines the result and result as output.

Implement Timers in Durable Functions

When trying to implement a long-running workflow, we always need to consider different scenarios like what will happen if any particular task is not completed within the mentioned time duration? In this situation, we can address this issue with the help of timeout and escalation paths. We can use the time within the Azure Durable Function with the help of orchestrator functions. We can implement delay or specify the timeout duration for any asynchronous actions. We can use the durable timers in the orchestrator function instead of using setTimeout() and setInterval() functions. 

Suppose, in the above workflow, we need to incorporate an escalation step to take action if a Leave Application does not approve within a specified duration. So, in this exercise, we will add a timer to control timeout during the workflow execution. For this, we need to perform the below steps,

Step 1 - Need to install the moment npm package

01. So before going to change into the workflow, we first install the required packages into the Function App.

02. We click on the App Service Editor under the Development Tools option.

03. Select WWWROOT Folder and click on the Open Console Options.

04. Run the below command into the console window.

npm install typescript
npm install moment

05. Once the package installation is completed, return to the Function App.

Step 2 - Create an Escalation Activity Function

01. Now, click on the Create Button under the Functions option.

02. Select the Durable Functions Activity template from the list in the Create Function section.

03. Provide the function name as Escalation and click on the create button.

04. Now open the newly created function in the code editor using the Code + Test option.

05. Replace the existing code with the below-mentioned code block 

module.exports = async function (context) {
    return `ESCALATION: You have not approved the Pending Leave Applications - reassigning them to your Reporting Manager!  ${context.bindings.name}!`;
};

06. Click on the Save button.

Step 3 - Update Orchestration Function to implement escalation process

01. Now, click on the Functions option.

02. From the Function List, select the OrchtrstFunction which we created in the previous section.

03. Now click on the Code + Test option under the Developer menu.

04. Make the changes in the function as below,

const moment = require("moment");
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
    const outputs = [];
    const deadline = moment.utc(context.df.currentUtcDateTime).add(20, "s");
    const activityTask = context.df.waitForExternalEvent("Approval");
    const timeoutTask = context.df.createTimer(deadline.toDate());

    const winner = yield context.df.Task.any([activityTask, timeoutTask]);
    if (winner === activityTask) {
        outputs.push(yield context.df.callActivity("LeaveApproval", "Approved"));
    }
    else
    {
        outputs.push(yield context.df.callActivity("Escalation", "Departmental HODs"));
    }
    if (!timeoutTask.isCompleted) {
        // All pending timers must be complete or canceled before the function exits.
        timeoutTask.cancel();
    }
    return outputs;
});

05. If the approval function does not respond within 20 seconds, the Escalation function will be executed. 

06. Click on the Save Button.

07. Now, we need to test it. 

08. For this, select the HttpStart Function from the Function List, and it will navigate to the function pane.

09. Click on the Get Function Url option in the top bar and copy the URL. The Url will name like this – 

https://azdemo-lmsapproval.azurewebsites.net/api/orchestrators/{functionName}?code=vPkV3NANoBkGvAOEXPbe8VoXGejFWqf2e1XLCLvjfk3e74jy5IzyAw==

10. We need to replace the keyword {functionName} with the Orchestrator function name. In our case, the orchestrator function name is OrchtrstFunction. So the final URL after modification will be as below– 

https://azdemo-lmsapproval.azurewebsites.net/api/orchestrators/OrchtrstFunction?code=vPkV3NANoBkGvAOEXPbe8VoXGejFWqf2e1XLCLvjfk3e74jy5IzyAw==

11. Open a new tab in the browser and paste the URL.

12. The response of the URL will be as below. But, first, we need to copy the statusQueryGetUri and paste it into the new browser tab.

13. The output of the statusQueryGetUri will be as below –

14. In the production, we can see that the status is shown as RUNNING as it is waiting for the timer countdown to 20 seconds.
 
15. So, wait for 20 seconds and refresh the browser. Now, we can find that as the Approval function is called, the process automatically calls the Escalation function as per the workflow defined.

Conclusion

This article discussed issues related to the workflow design of Azure Durable Functions. Also, we demonstrated how we can develop an approval process with the help of the Azure Durable Function Workflow. Any queries, suggestions, or feedback related to this article are always welcome.