Jasinski Technical Wiki

Navigation

Home Page
Index
All Pages

Quick Search
»
Advanced Search »

Contributor Links

Create a new Page
Administration
File Management
Login/Logout
Your Profile

Other Wiki Sections

Software

PoweredBy

Managing Durable Function Orchestrations - Azure and C#

RSS
Modified on Tue, Jun 14, 2022, 9:50 AM by Administrator Categorized as Azure

Overview

When working with Azure Durable Functions, it can be useful to terminate past orchestrations that are still running but no longer needed. This article provides a Azure function with an HTTP trigger that provides this functionality.

IT IS IMPORTANT NOT TO INCLUDE THIS CODE IN A PRODUCTION SITUATION, as security on it is insufficient. However, it does provide details around how this is accomplished.

Usage

1. Querying for running orchestrations

When you run the function app locally, the Command Window will display the URL for calling this function. It will likely be simliar to the following. Calling this URL — e.g., from Postman — will return a list of orchestrations that are currently running.

http://localhost:7071/api/OrchestrationManager

2. Terminating all running orchestrations

Adding the query string parameter "term=1" to the above URL will cause the code to terminate all running orchestrations, and return a list of these orchestrations that were terminated.

Code

public static class OrchestrationManagerFunctions
{
    [FunctionName(nameof(OrchestrationManager))]
    public static async Task<IActionResult> OrchestrationManager(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        [DurableClient] IDurableOrchestrationClient starter,
        ILogger log)
    {
        /*--- Inits ---*/
        log.LogInformation("C# HTTP trigger function processed a request.");

        var result = new List<string>();

        var token = new CancellationToken();

        /*--- Get/Display Orchestrations Currently Running ---*/
        var instances = await starter.ListInstancesAsync(new OrchestrationStatusQueryCondition { }, token);

        Debug.Print("=========================================================");
        Debug.Print("  Orchestrations Currently Running");
        Debug.Print("---------------------------------------------------------");

        foreach (var item in instances.DurableOrchestrationState)
        {
            if (item.RuntimeStatus != OrchestrationRuntimeStatus.Running)
            {
                continue;
            }

            var mgr = starter.CreateHttpManagementPayload(item.InstanceId);

            var url = mgr.TerminatePostUri;

            var msg = $"Instance('{item.InstanceId}') - {item.Name} - Since {item.CreatedTime}";

            result.Add(msg);

            Debug.Print(msg);
        }
        Debug.Print("=========================================================");

        /*--- Terminate All Running Instances ---*/
        var foo = req.Query["term"];

        if (Debugger.IsAttached && foo == "1")
        {
            foreach (var item in instances.DurableOrchestrationState)
            {
                if (item.RuntimeStatus != OrchestrationRuntimeStatus.Running)
                {
                    continue;
                }

                var mgr = starter.CreateHttpManagementPayload(item.InstanceId);

                var uri = new Uri(mgr.TerminatePostUri);

                var httpRequest = (HttpWebRequest)WebRequest.Create(uri);

                httpRequest.Method = "POST";

                var httpResponse = (HttpWebResponse)(await httpRequest.GetResponseAsync());

                var httpResult = await new StreamReader(httpResponse.GetResponseStream()).ReadToEndAsync();

                Debug.Print($"Instance('{item.InstanceId}') - {item.Name} - TERMINATED");
            }

            Debug.Print("=========================================================");
        }

        return new OkObjectResult(result);
    }
}

ScrewTurn Wiki version 3.0.1.400. Some of the icons created by FamFamFam. Except where noted, all contents Copyright © 1999-2022, Patrick Jasinski.