Setting up Orchestrations

Starting Orchestrations

Orchestrations with Durable Functions are started by using the StartNewAsync method on the DurableOrchestrationClient. An instance of DurableOrchestrationClient can be retrieved by using the OrchestrationClientAttribute binding. The binding can be paired with exiting function triggers.

[FunctionName("RunOrchestration")]
public static async Task<HttpResponseMessage> RunOrchestration(
    [HttpTrigger(AuthorizationLevel.Anonymous, "POST")]HttpRequestMessage req,
    [OrchestrationClient] DurableOrchestrationClient orchestrationClient)
{
    OrderRequestData data = await req.Content.ReadAsAsync<OrderRequestData>();
    string instanceId = await orchestrationClient.StartNewAsync("PlaceOrder", data);

    return orchestrationClient.CreateCheckStatusResponse(req, instanceId);
}

Takeaways

  • StartNewAsync method of DurableOrchestrationClient is used to start a stateful workflow.
  • StartNewAsync has overloads that accept input that may need to be passed to the orchestration.
  • The OrchestrationClient binding is used to get access to the DurableOrchestrationClient
  • The OrchestrationClient binding can be used with core Azure Functions triggers.

Read more

Authoring Orchestrator Functions

Orchestrator functions are responsible for managing the stateful workflows in Durable Functions. They take care of checkpointing progress and resuming workflows that are waiting for activities to complete. OrchestrationTriggerAttribute is used to annotate functions as orchestrator functions.

Orchestration functions support only DurableOrchestrationContext as a parameter type. DurableOrchestrationContext has methods that allow you to call activity functions, call sub-orchestrations, get input data for the orchestrator, and a few others.

[FunctionName("PlaceOrder")]
public static async Task<InvoiceData> OrderOrchestration([OrchestrationTrigger] DurableOrchestrationContext context)
{
    OrderRequestData orderData = context.GetInput<OrderRequestData>();

    //long running operation
    InvoiceData invoice = await context.CallActivityAsync<InvoiceData>("ProcessPayment", orderData);
    return invoice;
}

Takeaways

  • OrchestrationTriggerAttribute marks functions are orchestrator functions.
  • DurableOrchestrationContext is used to interact with the activity functions the make up the stateful workflow.
  • Orchestrator functions all run on a single dispatcher thread per host. Therefore, orchestrators should not perform any I/O operations.
  • Orchestrator functions can return output values. The output must be JSON-serializable.
  • A null value will be saved as the output if an orchestrator function returns Task or void.

Read more

Authoring Activity Functions

Activities are composed together in orchestrator functions to create a stateful workflow. Activities are where most of the processing happens for a given orchestration. ActivityTriggerAttribute is used to annotate functions as orchestration activities.

Activity functions can accept either an instance of DurableActivityContext or a JSON serializable type as a parameter. The return values are serialized to JSON and persisted to the orchestration history table when the orchestrator function does checkpointing.

 [FunctionName("CheckAndReserveInventory")]
 public static bool CheckAndReserveInventory([ActivityTrigger] DurableActivityContext context)
 {
     OrderRequestData orderData = context.GetInput<OrderRequestData>();

     // Check inventory system and reserve products
     return true;
 }

Takeaways

  • ActivityTriggerAttribute marks functions as orchestration activities.
  • DurableActivityContext can be used to access input values for the activities
  • Activities functions can return output values. The output must be JSON-serializable.
  • A null value will be saved as the output if an orchestrator function returns Task or void.

Read more