Saturday, 15 September 2018

Create Azure Durable Functions which includes Orchestrator Function and Activity Function - Part 2

In this post we are going to see the implementation of  Durable Function which includes Orchestrtor Function and Activity Function

Please click on the below link for the Azure Durable Function source code
AzureDurableFunctions Source Code


We will take a scenario, inside the Orchsetrator Function, we will call two Activity Function, one Activity function returns the books list and second activity will save the books list to the Azure Table Storage.

1. Create a New Project
2. Select cloud in the left pane
3. Select Azure Functions in the right pane.
4. Give Azure Function name as "BookFunction" and click ok.



5. Select the HttpTrigger from the menu
6. Click ok




7. Install the following nuget package in the solution

Microsoft.Azure.WebJobs.Extensions.DurableTask




8. Change the input parameter for the function. add the OrchestrationClient Attribute with     
    DurableOrchestrationClient

[OrchestrationClient]DurableOrchestrationClient starter,



9. TestFunction.cs
******************


public static class TestFunction
    {
        [FunctionName("TestFunction")]
        public static async Task<HttpResponseMessage> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post",
                         Route = null)]HttpRequestMessage req,
            [OrchestrationClient]DurableOrchestrationClient starter,
            TraceWriter log)
        {
            log.Info("C# HTTP trigger function processed a request.");
            // Function input comes from the request content.
            string instanceId = await starter.StartNewAsync("Orchestrator", "TedTalk");

            log.Info($"Started orchestration with ID = '{instanceId}'.");
               
            return starter.CreateCheckStatusResponse(req, instanceId);
        }       
        

    }


Let we start the Program for Azure Durable Functions. From the above code you can see that we are calling a durable function Orchestrator  await starter.StartNewAsync("Orchestrator""TedTalk");


10. Add another Function named it as OrchestratorFunction , It is decorated by [OrchestrationTrigger] with DurableOrchestrationContext, Now if you see inside the function we are calling two Activity function named "GetAllData" and "SaveData"

OrchestratorFunction.cs
*********************************


    public class OrchestratorFunction
    {
        [FunctionName("Orchestrator")]
        public static async Task<string> RunOrchestrator([OrchestrationTrigger]
                 DurableOrchestrationContext context)
        {
            var name = context.GetInput<string>();

            // retrieves the list of data by invoking a separate Activity Function.
            var books = await context.CallActivityAsync<List<Book>>("GetAllData", name);
            if (books.Count > 0)
            {
                //Saving the retrieved data to table
                await context.CallActivityAsync("SaveData", books);
            }
            return context.InstanceId;
        }

    }



11. Add another Function named it as ActivityFunction, It is decorated by [ActivityTrigger] with DurableActivityContext, Now create two functions inside the file one is for "GetAllData" another one is for "SaveData", This two activity functions are called inside orchestration function.

GetAllData: This activity function will return the list of books
SaveData: This activity function will save the books list to Azure Table Storage.




ActivityFunction.cs
******************************


public static class ActivityFunction
    {
        private static CloudStorageAccount account = CloudStorageAccount.Parse(Environment.GetEnvironmentVariable("AzureWebJobsStorage",                                    EnvironmentVariableTarget.Process));

        
        [FunctionName("GetAllData")]
        public static async Task<List<Book>> GetAllData( 
                            [ActivityTrigger]DurableActivityContext context)
        {
            // retrieves the book name from the Orchestrator function
            var organizationName = context.GetInput<string>();

            return new List<Book> { new Book{ Id = 1, Name = "C#" }, 
                                    new Book{ Id = 2, Name = "Java" } };
        }



        [FunctionName("SaveData")]
        public static async Task SaveData([ActivityTrigger]DurableActivityContext context)
        {
            // retrieves a list of books from the Orchestrator function
            var books = context.GetInput<List<Book>>();

            // create a table storage client
            var client = account.CreateCloudTableClient();
            var table = client.GetTableReference("Books");

            await table.CreateIfNotExistsAsync();

            TableBatchOperation tableBatchOperations = new TableBatchOperation();

            for(int i=0; i<books.Count; i++)
            {
                tableBatchOperations.Add(TableOperation.InsertOrMerge(
                    new BookRepository(books[i].Id)
                    {
                        Name = books[i].Name
                    }));
            }

            await table.ExecuteBatchAsync(tableBatchOperations);

        }
    }

    public class BookRepository: TableEntity
    {
        public BookRepository(int id)
        {
            PartitionKey = "TechnicalBooks";
            RowKey = id.ToString();
        }

        public string Name { set; get; }
    }

    public class Book
    {
        public int Id { get; set; }

        public string Name { get; set; }


    }


Now change values in the local.settins.json for AzureWebJobsStorage to connect the azure table storage.

{
    "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "AzureWebJobsDashboard": "UseDevelopmentStorage=true"
  }

}



12. Now run the application, it will results in display the window like below




13. In the console Windows you can see the http url to hit the function, copy that url and paste that in browser. Now Orchestrator Function will be hit and two Activity Functions will be executed.




14. You see the Azure table storage , you can see the data populated from activity function.




Full source code:
*******************
Please click on the below link for the Azure Durable Function source code

AzureDurableFunctions Source Code


From this post you can learn how to use the Azure Durable Functions which includes Orchestrator Function and Activity Function.