Skip to content
Petkir Blog
XLinkedinBluesky

Azure Durable Functions - Function Chaining and Delays with .NET 8 Isolated

Code, Azure2 min read

What is Function Chaining?

Function Chaining is a common pattern in Azure Durable Functions where you chain multiple functions together in a sequence. Each function depends on the output of the previous one. This pattern allows you to break down complex workflows into smaller, manageable steps.

In a Durable Function, each step (activity) is defined as a separate function, and the Orchestrator Function manages the workflow. It ensures that each function executes in sequence, passing the result from one function to the next.

Why Use Delays in Function Chaining?

In certain workflows, you might need to introduce a delay between steps. For example, you may want to wait before executing the next function in a sequence due to business logic (e.g., waiting for an external process or checking the status of an operation at regular intervals).

Azure Durable Functions make it easy to introduce delays with the CreateTimer API, which pauses the orchestration for a specified amount of time without holding any system resources.

Simple Sample: Function Chaining with Delay in .NET 8 Isolated

DurableFunctionChaining.cs

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System.Net;
using System.Threading.Tasks;
using System;
public class DurableFunctionChaining
{
private readonly ILogger _logger;
public DurableFunctionChaining(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<DurableFunctionChaining>();
}
[Function("ChainingHttpStart")]
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)
{
var step1Result = await context.CallActivityAsync<string>(nameof(StepOne), "Input for Step 1");
_logger.LogInformation($"Step 1 completed with result: {step1Result}");
// Adding a delay of 5 seconds between steps
var delayDuration = TimeSpan.FromSeconds(5);
await context.CreateTimer(context.CurrentUtcDateTime.Add(delayDuration), CancellationToken.None);
_logger.LogInformation($"Delay of {delayDuration.Seconds} seconds completed.");
var step2Result = await context.CallActivityAsync<string>(nameof(StepTwo), step1Result);
_logger.LogInformation($"Step 2 completed with result: {step2Result}");
}
[Function("StepOne")]
public string StepOne([ActivityTrigger] string input)
{
return $"Processed Step 1 with input: {input}";
}
[Function("StepTwo")]
public string StepTwo([ActivityTrigger] string input)
{
return $"Processed Step 2 with input: {input}";
}
}

Program.cs

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Functions.Worker.Extensions.DurableTask;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureLogging(logging =>
{
logging.AddConsole();
})
.Build();
host.Run();
### Key Points:
1. **Function Chaining**: In this example, two functions (StepOne and StepTwo) are chained together. The result of StepOne is passed to StepTwo.
2. **Introducing Delay**: A 5-second delay is added between the two steps using CreateTimer in the orchestrator.
3. **Orchestration Flow**: The orchestrator function manages the workflow, ensuring the functions execute in sequence, with a delay between them.
### Conclusion
The Function Chaining pattern is a powerful tool in Azure Durable Functions for managing workflows where tasks need to be executed in sequence.
Introducing a delay between chained functions allows you to build more sophisticated and time-sensitive workflows.
Using the Isolated Process model in .NET 8, you gain flexibility and future-proof your application as you manage stateful workflows in the cloud.