Durable Functions – Orchestrators for Azure
Functions
Reduce ComplexitySimplify
Enable Long Running FunctionsEnable
Orchestrate FunctionsCoordinate
Why do we need “Durable Functions”
Long Running &
Local State
01
Simplify
Function
Coordination
02
Easy Function
Communication
03
Code-Only
04
What is Durable Functions?
Automatic Save of
Local State
03
No JSON
schemas,
No designer!
01
Sync & Async
Functions Calls
02
F1 F2 F3 F4
// calls functions in sequence
public static async Task<object> Run(DurableOrchestrationContext ctx)
{
try
{
var x = await ctx.CallFunctionAsync("F1");
var y = await ctx.CallFunctionAsync("F2", x);
var z = await ctx.CallFunctionAsync("F3", y);
return await ctx.CallFunctionAsync("F4", z);
}
catch (Exception)
{
// global error handling/compensation goes here
}
}
F1
F2
F3
public static async Task Run(DurableOrchestrationContext ctx)
{
var parallelTasks = new List<Task<int>>();
// get a list of N work items to process in parallel
object[] workBatch = await ctx.CallFunctionAsync<object[]>("F1");
for (int i = 0; i < workBatch.Length; i++)
{
Task<int> task = ctx.CallFunctionAsync<int>("F2", workBatch[i]);
parallelTasks.Add(task);
}
await Task.WhenAll(parallelTasks);
// aggregate all N outputs and send result to F3
int sum = parallelTasks.Sum(t => t.Result);
await ctx.CallFunctionAsync("F3", sum);
}
Request Approval
Function
Escalate Function
Process Approval
Function
public static async Task Run(DurableOrchestrationContext ctx)
{
await ctx.CallFunctionAsync<object[]>("RequestApproval");
using (var timeoutCts = new CancellationTokenSource())
{
DateTime dueTime = ctx.CurrentUtcDateTime.AddHours(72);
Task durableTimeout = ctx.CreateTimer(dueTime, 0, cts.Token);
Task<bool> approvalEvent = ctx.WaitForExternalEvent<bool>("ApprovalEvent");
if (approvalEvent == await Task.WhenAny(approvalEvent, durableTimeout))
{
timeoutCts.Cancel();
await ctx.CallFunctionAsync("HandleApproval", approvalEvent.Result);
}
else
{
await ctx.CallFunctionAsync("Escalate");
}
}
}
Worker
Worker
Worker
Worker
Worker
Stateful/Partitioned
Stateless
Control Queue(s)
Triggers orchestrator
function execution
Work Item Queue
Triggers activity function execution
History & Instance Tables
Key Takeaways - Orchestrator functions
Code Stateful Durable
When
sleeping, not
billed
Automatically
wake up
Scalable

Azure Durable Functions

  • 2.
    Durable Functions –Orchestrators for Azure Functions Reduce ComplexitySimplify Enable Long Running FunctionsEnable Orchestrate FunctionsCoordinate
  • 3.
    Why do weneed “Durable Functions” Long Running & Local State 01 Simplify Function Coordination 02 Easy Function Communication 03 Code-Only 04
  • 4.
    What is DurableFunctions? Automatic Save of Local State 03 No JSON schemas, No designer! 01 Sync & Async Functions Calls 02
  • 5.
  • 7.
    // calls functionsin sequence public static async Task<object> Run(DurableOrchestrationContext ctx) { try { var x = await ctx.CallFunctionAsync("F1"); var y = await ctx.CallFunctionAsync("F2", x); var z = await ctx.CallFunctionAsync("F3", y); return await ctx.CallFunctionAsync("F4", z); } catch (Exception) { // global error handling/compensation goes here } }
  • 8.
  • 10.
    public static asyncTask Run(DurableOrchestrationContext ctx) { var parallelTasks = new List<Task<int>>(); // get a list of N work items to process in parallel object[] workBatch = await ctx.CallFunctionAsync<object[]>("F1"); for (int i = 0; i < workBatch.Length; i++) { Task<int> task = ctx.CallFunctionAsync<int>("F2", workBatch[i]); parallelTasks.Add(task); } await Task.WhenAll(parallelTasks); // aggregate all N outputs and send result to F3 int sum = parallelTasks.Sum(t => t.Result); await ctx.CallFunctionAsync("F3", sum); }
  • 11.
  • 12.
    public static asyncTask Run(DurableOrchestrationContext ctx) { await ctx.CallFunctionAsync<object[]>("RequestApproval"); using (var timeoutCts = new CancellationTokenSource()) { DateTime dueTime = ctx.CurrentUtcDateTime.AddHours(72); Task durableTimeout = ctx.CreateTimer(dueTime, 0, cts.Token); Task<bool> approvalEvent = ctx.WaitForExternalEvent<bool>("ApprovalEvent"); if (approvalEvent == await Task.WhenAny(approvalEvent, durableTimeout)) { timeoutCts.Cancel(); await ctx.CallFunctionAsync("HandleApproval", approvalEvent.Result); } else { await ctx.CallFunctionAsync("Escalate"); } } }
  • 13.
    Worker Worker Worker Worker Worker Stateful/Partitioned Stateless Control Queue(s) Triggers orchestrator functionexecution Work Item Queue Triggers activity function execution History & Instance Tables
  • 14.
    Key Takeaways -Orchestrator functions Code Stateful Durable When sleeping, not billed Automatically wake up Scalable

Editor's Notes

  • #6 Add master slave
  • #8 CallFunctionAsync uses queues under the covers, thus they can be scaled out to multiple VMs.
  • #12 Aks how many people have experience with coding? Encouraging Developer driven world
  • #13 We will expose a mechanism for sending named events to an orchestrator from outside the orchestration context – e.g. REST API and/or output binding.
  • #14 Detailed design is pending.