2
votes

I have a use case which requires me to fire some Azure Durable Functions without caring about its results, and I was wondering if my approach is the correct one.

This is the scenario I'm in:

  • Function A uses an HttpTrigger
  • Function B uses an ActivityTrigger

This is my workflow:

  • A is invoked and needs to do some business logic
  • Alongside this business logic, I need to do a long background task that may or may not fail. I don't care about the results, but I need to run this task everytime A is invoked.
  • A needs to return as quick as possible, that's why I can't wait for the background task to finish
  • B takes care of this background task while A returns

All the Durable Functions examples that I'm finding online show something like this:

await starter.StartNewAsync("BackgroundDurableFunction", data)

My issue is here is that I don't want to await the Durable Function but I need it to just run in background and do its things (mostly network I/O).

To avoid waiting for this Durable Function I ended up with this workaround:

Task.Factory.StartNew(() => starter.StartNewAsync("BackgroundDurableFunction", data));

This seems to work just right, as I don't need to await anything, but after reading The Dangers of Task.Factory.StartNew I'm a little bit scared that this might be a dangerous solution.

So, the question is: what's the correct way to start a Durable Function and have it run in background without caring about its results (and without having warnings about not waiting for the task)?

1

1 Answers

3
votes

Yes, durable functions should work well for your scenario. You are just missing one thing: The Orchestrator. This should get you started:

[FunctionName("MyHttpTriggered")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req, ILogger log,
[OrchestrationClient] DurableOrchestrationClient starter)
{
    string data = "hello";
    string instanceId = await starter.StartNewAsync("MyOrchestrator", data);
    return new OkObjectResult($"Orchestrator started. Instance ID={instanceId}");
}

[FunctionName("MyOrchestrator")]
public static async Task MyOrchestrator(
[OrchestrationTrigger] DurableOrchestrationContext context, ILogger log)
{
    string data = context.GetInput<string>();
    await context.CallActivityAsync("YourActivityFunction", data);
}

[FunctionName("YourActivityFunction")]
public static async Task YourActivityFunction([ActivityTrigger] string data, ILogger log)
{

    // do whatever here

}

While there are await statements, this is truly fire and forget. The opposite would be a fan-in pattern. In this case you basically do a fan-out without the fan-in.