Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Durable functions

68 views

Published on

Azure Functions Durable functions

Published in: Technology
  • Be the first to comment

Durable functions

  1. 1. “Hello Seoul!”[“Hello Seoul!”] Orchestrator Function Activity Function Execution History var outputs = new List<string>(); outputs.Add(await context.CallActivityAsync<string>("SayHello", “Seoul")); return outputs; Orchestrator Function ? Activity Function “Hello Seoul!” Orchestrator Started Execution Started Task Scheduled, SayHello, “Seoul” Orchestrator Completed Task Completed, “Hello Seoul!” Orchestrator Started Execution Completed, ["Hello Seoul!"] Orchestrator Completed
  2. 2. [FunctionName(nameof(ActivityFn))] public static string ActivityFn( [ActivityTrigger] DurableActivityContext context, ILogger log) { string name = context.GetInput<string>(); string instanceId = context.InstanceId; log.LogInformation($"[{instanceId}] Saying hello to {name}."); return $"Hello {name}!"; } { "name": "<Name of input parameter in function signature>", "activity": "<Optional - name of the activity>", "type": "activityTrigger", "direction": "in" }
  3. 3. [FunctionName(nameof(OrchestratorFn))] public static async Task<List<string>> OrchestratorFn( [OrchestrationTrigger] DurableOrchestrationContext context) { var outputs = new List<string>(); outputs.Add(await context.CallActivityAsync<string>(nameof(ActivityFn), "Seoul")); outputs.Add(await context.CallActivityAsync<string>(nameof(ActivityFn), "Busan")); outputs.Add(await context.CallActivityAsync<string>(nameof(ActivityFn), "Incheon")); return outputs; } { "name": "<Name of input parameter in function signature>", "orchestration": "<Optional - name of the orchestration>", "type": "orchestrationTrigger", "direction": "in" }
  4. 4. [FunctionName(nameof(ClientFn))] public static async Task<HttpResponseMessage> ClientFn( [HttpTrigger(AuthorizationLevel.Anonymous, "get")]HttpRequestMessage req, [OrchestrationClient]DurableOrchestrationClient starter, ILogger log) { string instanceId = await starter.StartNewAsync(nameof(OrchestratorFn), null); log.LogInformation($"Started orchestration with ID = '{instanceId}'."); return starter.CreateCheckStatusResponse(req, instanceId); } { "name": "<Name of input parameter in function signature>", "taskHub": "<Optional - name of the task hub>", "connectionName": "<Optional - name of the connection string app setting>", "type": "orchestrationClient", "direction": "in" }
  5. 5. public class DurableOrchestrationClient : DurableOrchestrationClientBase { … Task<string> StartNewAsync(…); … Task TerminateAsync(…); … Task<IList<DurableOrchestrationStatus>> GetStatusAsync(…); … Task TerminateAsync(…); … HttpResponseMessage CreateCheckStatusResponse(…); } public class DurableOrchestrationStatus { public string Name { get; } public string InstanceId { get; } public DateTime CreatedTime { get; } public DateTime LastUpdatedTime { get; } public JToken Input { get; } public JToken Output { get; } public OrchestrationRuntimeStatus RuntimeStatus { get; } public JToken CustomStatus { get; } public JArray History { get; } }
  6. 6. Pattern #1: Function Chaining 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 } }
  7. 7. Pattern #2: Fan-Out/Fan-In F1 F2 F3
  8. 8. 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.CallActivityAsync<object[]>("F1"); for (int i = 0; i < workBatch.Length; i++) { Task<int> task = ctx.CallActivityAsync<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.CallActivityAsync("F3", sum); }
  9. 9. Pattern #3: HTTP Async Response Start DoWork GetStatus
  10. 10. > curl -X POST https://myfunc.azurewebsites.net/orchestrators/DoWork -H "Content-Length: 0" -i HTTP/1.1 202 Accepted Location: https://myfunc.azurewebsites.net/orchestrators/b79baf67f717453ca9e86c5da21e03ec Server: Microsoft-IIS/8.0 > curl https://myfunc.azurewebsites.net/orchestrators/b79baf67f717453ca9e86c5da21e03ec -i HTTP/1.1 202 Accepted Content-Length: 173 Content-Type: application/json Location: https://myfunc.azurewebsites.net/orchestrators/b79baf67f717453ca9e86c5da21e03ec Server: Microsoft-IIS/8.0 {"runtimeStatus":"Running","createdTime":"2017-03-16T21:20:36Z","lastUpdatedTime":"2017-03- 16T21:20:47Z"} > curl https://myfunc.azurewebsites.net/orchestrators/b79baf67f717453ca9e86c5da21e03ec -i HTTP/1.1 200 OK Content-Length: 175 Content-Type: application/json Server: Microsoft-IIS/8.0 {"runtimeStatus":"Completed","createdTime":"2017-03-16T21:20:36Z","lastUpdatedTime":"2017-03- 16T21:20:57Z"}
  11. 11. Worker Worker Worker Worker Worker Stateful/Partitioned Stateless Control Queue(s) Triggers orchestrator function execution Work Item Queue Triggers activity function execution History Table
  12. 12. Event Sourcing Orchestrator code must be deterministic

×