Skip to content
Petkir Blog
XLinkedinBluesky

Azure Durable Functions - Human Interaction Pattern with .NET 8 Isolated

Code, Azure2 min read

What is the Human Interaction Pattern?

The Human Interaction pattern in Azure Durable Functions is designed to manage workflows that require human input or intervention. This pattern allows a function to pause and wait for user input or action before continuing with the next steps in the workflow. It is particularly useful for scenarios such as approvals, confirmations, or any action that needs human intervention.

Why Use the Human Interaction Pattern?

In automated workflows, there are often points where decisions must be made by a human rather than a machine. The Human Interaction pattern enables developers to:

  • Pause orchestration and wait for user input.
  • Capture responses and use them to determine the next steps in the workflow.
  • Build more interactive and dynamic applications that require human involvement.

Simple Sample: Human Interaction Pattern

In this example, we will demonstrate how to implement the Human Interaction pattern using Azure Durable Functions with .NET 8 Isolated.

`DurableFunctionHumanInteraction.cs``

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System.Net;
using System.Threading.Tasks;
public class DurableFunctionHumanInteraction
{
private readonly ILogger _logger;
public DurableFunctionHumanInteraction(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<DurableFunctionHumanInteraction>();
}
[Function("HumanInteractionHttpStart")]
public async Task<HttpResponseData> HttpStart(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client)
{
var instanceId = await client.StartNewAsync(nameof(RunOrchestrator), null);
_logger.LogInformation($"Started orchestration with ID = '{instanceId}'.");
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync($"Orchestration started with ID: {instanceId}");
return response;
}
[Function("RunOrchestrator")]
public async Task RunOrchestrator([DurableOrchestrationTrigger] IDurableOrchestrationContext context)
{
_logger.LogInformation("Waiting for human interaction...");
// Pause the orchestration until human input is received
var userResponse = await context.WaitForExternalEvent<string>("UserInputEvent");
_logger.LogInformation($"Received user response: {userResponse}");
// Continue processing based on user input
if (userResponse == "approve")
{
_logger.LogInformation("User approved the action.");
// Proceed with the next steps in the workflow
}
else
{
_logger.LogInformation("User rejected the action.");
// Handle rejection appropriately
}
}
[Function("ReceiveUserInput")]
public async Task ReceiveUserInput(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client)
{
var input = await req.ReadAsStringAsync();
var instanceId = req.Headers["InstanceId"]; // Assuming the instance ID is passed in headers
// Raise the external event to resume the orchestration
await client.RaiseEventAsync(instanceId, "UserInputEvent", input);
}
}

Program.cs

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Functions.Worker.Extensions.DurableTask;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(worker =>
{
worker.UseDurableTask();
})
.ConfigureLogging(logging =>
{
logging.AddConsole();
})
.Build();
host.Run();

Key Points:

  1. Waiting for Input: The orchestration function pauses and waits for human input using WaitForExternalEvent.

  2. Receiving Input: A separate function (ReceiveUserInput) listens for user responses, which can be triggered via an HTTP request.

  3. Dynamic Workflow: The workflow can change based on the user's input, allowing for more interactive applications.

Conclusion

The Human Interaction pattern in Azure Durable Functions provides a powerful way to incorporate human decision-making into automated workflows. By pausing for user input and resuming based on responses, developers can create dynamic applications that respond to human actions. Using the Isolated Process model in .NET 8 ensures flexibility and future-proofing for these workflows.