Azure Functions with Durable Functions extension

Durable Functions extension was the missing piece in Azure functions and with it the Azure functions are so much more convenient to use. With Durable Functions we can implement advanced workflows, long running tasks, timers, error handling, diagnostics... a lot easier that we could with bare Azure functions.

This is all possible with Durable Functions. In Durable functions extension introduces the so called Orchestrator function, which is stateful and can call Activity functions that have the same behaviour as regular queue-triggered functions. The orchestrator function is crucial in Durable Functions extension and makes possible all the functionallity listed.

Orchestrator function

Once the Orchestrator function starts, it executes until the first await statement -> call of an activity function. Then the following happens: once the await statement is hit, the Orchestrator function checkpoints -> that means it saves it's state in the History table. Then a message is put on the work item queue. This is the trigger for the activity function to start executing and the orchestrator function is removed from memory. Once removed from memory, the billing for orchestrator function stops.

After the activity function ends it writes a message on the so called Control queue, which this is a trigger for the Orchestrator function to restore state from History table. In reality Orchestrator function replays to the point where it previously checkpointed.

You can check the History table and queues (control and work items) with Azure Storage explorer.

Orchestrator function constraints Orchestrator function comes with constraints we have to consider.

  • non-blocking
  • infinite loops avoided -> growing orchestration history
  • never initiate an async operation

Orchestrator function should be "light" and only responsible for controlling workflows and error handling/diagnostics.

Activity function

Activity function is actually an ordinary Azure function. It's stateless and can freely scale out to an unbounded number of VMs. We can safely put I/O operations, CPU intensive operations and use multiple threads in the activity function.

Develop Azure Functions locally


Debugging Orchestrator function

When debugging an Orchestrator function we will notice that after some activity, the function ends, the debugger jumps to the start of the orchestrator function and at first it looks like the Orchestrator function executes once again. But the truth is that orchestrator function just restoring state from the History table (DurableOrchestrationContext.IsReplaying property)