I am trying to have an Azure Durable Function with Fan-out/Fan-in in C#.
For my orchestrator, I have the following signature.
public static async Task TimerStart([TimerTrigger("0 */15 * * * *", RunOnStartup = true)] TimerInfo myTimer, [Microsoft.Azure.Functions.Worker.DurableClient] DurableTaskClient client, IDurableOrchestrationContext orchestrationContext)
The problem is how to call the Activity function.
I am getting orchestrationContext
as null.
Edit 1:
After input from Ikhtesam Afrin, I updated the code to the following:
public static async Task TimerStart([TimerTrigger("0 */15 * * * *", RunOnStartup = true)] TimerInfo myTimer, [DurableClient] DurableTaskClient client, TaskOrchestrationContext executionContext)
Still the variable executionContext
is null. I have checked the references in csproj. They are in order.
It is an isolated function.
IDurableOrchestrationContext
is being used for in-process function but it looks like you have created isolated durable function as you are using Microsoft.Azure.Functions.Worker.DurableClient package in your code. For isolated function, you need to use TaskOrchestrationContext.
I have created the below durable function which worked as expected.
using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;
using Microsoft.Extensions.Logging;
namespace _79098074
{
public static class OrchestrationFunction
{
[Function(nameof(OrchestrationFunction))]
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
ILogger logger = context.CreateReplaySafeLogger(nameof(OrchestrationFunction));
logger.LogInformation("Saying hello.");
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Seattle"));
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "London"));
return outputs;
}
[Function(nameof(SayHello))]
public static string SayHello([ActivityTrigger] string name, FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger("SayHello");
logger.LogInformation("Saying hello to {name}.", name);
return $"Hello {name}!";
}
[Function("Function1_TimerStart")]
public static async Task TimerStart(
[TimerTrigger("0 */5 * * * *")] TimerInfo timer,
[DurableClient] DurableTaskClient client,
FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger("Function1_TimerStart");
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
nameof(OrchestrationFunction));
logger.LogInformation("Started orchestration with ID = '{instanceId}' via TimerTrigger.", instanceId);
}
}
}
You need to have correct packages in .csproj file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>_79098074</RootNamespace>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.23.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.1.7" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.3.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.18.1" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.4.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
</ItemGroup>
</Project>
I am getting expected response.
Azure Functions Core Tools
Core Tools Version: 4.0.6517 Commit hash: N/A +6ee985b96787d19ddb1e56c5405f73fd3be9a32e (64-bit)
Function Runtime Version: 4.1036.1.23224
[2024-10-17T13:53:42.658Z] Found C:\Users\*******\79098074.csproj. Using for user secrets file configuration.
[2024-10-17T13:53:47.675Z] Azure Functions .NET Worker (PID: 26456) initialized in debug mode. Waiting for debugger to attach...
[2024-10-17T13:53:47.736Z] Worker process started and initialized.
Functions:
Function1_TimerStart: timerTrigger
OrchestrationFunction: orchestrationTrigger
SayHello: activityTrigger
For detailed output, run func with --verbose flag.
[2024-10-17T13:53:52.740Z] Host lock lease acquired by instance ID '0000000000000000000000000D2022A4'.
[2024-10-17T13:55:00.086Z] Executing 'Functions.Function1_TimerStart' (Reason='Timer fired at 2024-10-17T19:25:00.0406031+05:30', Id=32f10855-20df-4275-9120-9f611386fa3b)
[2024-10-17T13:55:00.472Z] Scheduling new OrchestrationFunction orchestration with instance ID '2e217858ec5043d6ac2ba51546aab827' and 0 bytes of input data.
[2024-10-17T13:55:00.791Z] Started orchestration with ID = '2e217858ec5043d6ac2ba51546aab827' via TimerTrigger.
[2024-10-17T13:55:00.841Z] Executed 'Functions.Function1_TimerStart' (Succeeded, Id=32f10855-20df-4275-9120-9f611386fa3b, Duration=789ms)
[2024-10-17T13:55:00.922Z] Executing 'Functions.OrchestrationFunction' (Reason='(null)', Id=fb02e535-f75c-4f14-a913-69eec630371e)
[2024-10-17T13:55:01.196Z] Saying hello.
[2024-10-17T13:55:01.292Z] Executed 'Functions.OrchestrationFunction' (Succeeded, Id=fb02e535-f75c-4f14-a913-69eec630371e, Duration=402ms)
[2024-10-17T13:55:01.421Z] Executing 'Functions.SayHello' (Reason='(null)', Id=f73fd98e-fe41-4135-bc5f-28d6d92dd34c)
[2024-10-17T13:55:01.440Z] Saying hello to Tokyo.
[2024-10-17T13:55:01.458Z] Executed 'Functions.SayHello' (Succeeded, Id=f73fd98e-fe41-4135-bc5f-28d6d92dd34c, Duration=42ms)
[2024-10-17T13:55:01.556Z] Executing 'Functions.OrchestrationFunction' (Reason='(null)', Id=a94a6f54-17bf-4be0-bf47-2964e39d0d22)
[2024-10-17T13:55:01.597Z] Executed 'Functions.OrchestrationFunction' (Succeeded, Id=a94a6f54-17bf-4be0-bf47-2964e39d0d22, Duration=46ms)
[2024-10-17T13:55:01.653Z] Executing 'Functions.SayHello' (Reason='(null)', Id=4ddaee59-10b6-42e0-a2c8-ae3d6d0c6d13)
[2024-10-17T13:55:01.666Z] Saying hello to Seattle.
[2024-10-17T13:55:01.676Z] Executed 'Functions.SayHello' (Succeeded, Id=4ddaee59-10b6-42e0-a2c8-ae3d6d0c6d13, Duration=22ms)
[2024-10-17T13:55:01.739Z] Executing 'Functions.OrchestrationFunction' (Reason='(null)', Id=a9f3c77e-cedd-4eb8-8ded-a2b297b2d086)
[2024-10-17T13:55:01.771Z] Executed 'Functions.OrchestrationFunction' (Succeeded, Id=a9f3c77e-cedd-4eb8-8ded-a2b297b2d086, Duration=31ms)
[2024-10-17T13:55:01.827Z] Executing 'Functions.SayHello' (Reason='(null)', Id=9a67f798-a7f2-4012-ba0f-48947ff656ff)
[2024-10-17T13:55:01.839Z] Saying hello to London.
[2024-10-17T13:55:01.851Z] Executed 'Functions.SayHello' (Succeeded, Id=9a67f798-a7f2-4012-ba0f-48947ff656ff, Duration=24ms)
[2024-10-17T13:55:01.910Z] Executing 'Functions.OrchestrationFunction' (Reason='(null)', Id=a5452599-a604-4ca1-9fee-36365d9682bd)
[2024-10-17T13:55:01.948Z] Executed 'Functions.OrchestrationFunction' (Succeeded, Id=a5452599-a604-4ca1-9fee-36365d9682bd, Duration=37ms)