public static async Task Run( [OrchestrationTrigger] DurableOrchestrationContextBase context, ILogger log) { var input = context.GetInput <MessageInput>(); var smsKey = await context.CallActivityAsync <string>("A_SaveTwilioMapping", context.InstanceId); input.SmsKey = smsKey; await context.CallActivityAsync <string>("A_SendTwilioText", input); var status = await context.WaitForExternalEvent <string>("TwilioCallback"); log.LogWarning("Got a status from Twilio! " + status); }
public static async Task <List <CartData> > Run([OrchestrationTrigger] DurableOrchestrationContextBase context, TraceWriter log) { var cart = context.GetInput <List <CartData> >() ?? new List <CartData>(); var addItemTask = context.WaitForExternalEvent <CartData>(CartEvents.AddItem); var removeItemTask = context.WaitForExternalEvent <CartData>(CartEvents.RemoveItem); var isCompletedTask = context.WaitForExternalEvent <bool>(CartEvents.IsCompleted); var setCartReminder = context.WaitForExternalEvent <CartReminderData>(CartEvents.SetReminder); // Wait for any external event var resultingEvent = await Task.WhenAny(addItemTask, removeItemTask, isCompletedTask, setCartReminder); // Add item to cart if (resultingEvent == addItemTask) { cart.Add(addItemTask.Result); context.SetCustomStatus("readynow"); if (!context.IsReplaying) { log.Info($"Added {addItemTask.Result.ItemName} to the Shopping Cart."); } } // Remove Item from cart else if (resultingEvent == removeItemTask) { cart.Remove(cart.Find(x => x.ItemId == removeItemTask.Result.ItemId)); context.SetCustomStatus("readynow"); if (!context.IsReplaying) { log.Info($"Removed {removeItemTask.Result.ItemName} from the Shopping Cart."); } } // Add reminder for cart (used to notify user of waiting cart with items) else if (resultingEvent == setCartReminder) { var provisionTask = context.CallSubOrchestratorAsync("SetCartNotificationTimer", setCartReminder.Result); if (!context.IsReplaying) { log.Info($"Added timer ({setCartReminder.Result.RemindInMinutes} minutes) for Shopping Cart."); } } // Complete cart or stay running ? if (resultingEvent == isCompletedTask && isCompletedTask.Result) { if (!context.IsReplaying) { log.Info("Completed the Shopping Cart."); } } else { context.ContinueAsNew(cart); // the magic line if (!context.IsReplaying) { log.Info($"cartList Count: {cart.Count}"); } } return(await Task.FromResult(cart)); }
public static async Task <string> GetApprovalOrchestrator([OrchestrationTrigger] DurableOrchestrationContextBase ctx, ILogger log) { var approvalConfig = ctx.GetInput <ApprovalConfig>(); string result; var expireAt = ctx.CurrentUtcDateTime.AddMinutes(approvalConfig.TimeoutMinutes); for (var n = 0; n < approvalConfig.ApproverCount; n++) { // todo: send a message to each approver if (!ctx.IsReplaying) { log.LogInformation($"Requesting approval from Approver {n + 1}"); } } var cts = new CancellationTokenSource(); var timerTask = ctx.CreateTimer(expireAt, cts.Token); var approvers = new HashSet <string>(); while (true) { var externalEventTask = ctx.WaitForExternalEvent <ApprovalResult>(ApprovalResultEventName); var completed = await Task.WhenAny(timerTask, externalEventTask); if (completed == timerTask) { result = $"Timed out with {approvers.Count} approvals so far"; if (!ctx.IsReplaying) { log.LogWarning(result); } break; // end orchestration } else if (completed == externalEventTask) { var approver = externalEventTask.Result.Approver; if (externalEventTask.Result.Approved) { approvers.Add(approver); if (!ctx.IsReplaying) { log.LogInformation($"Approval received from {approver}"); } if (approvers.Count >= approvalConfig.RequiredApprovals) { result = $"Approved ({approvers.Count} approvals received)"; if (!ctx.IsReplaying) { log.LogInformation(result); } break; } } else { result = $"Rejected by {approver}"; if (!ctx.IsReplaying) { log.LogWarning(result); } break; } } else { throw new InvalidOperationException("Unexpected result from Task.WhenAny"); } } cts.Cancel(); return(result); }
public static async Task <OrderResult> ProcessOrder( [OrchestrationTrigger] DurableOrchestrationContextBase ctx, ILogger log) { var order = ctx.GetInput <Order>(); order.OrchestrationId = ctx.InstanceId; if (!ctx.IsReplaying) { log.LogInformation($"Processing order #{order.Id}"); } var total = order.Items.Sum(i => i.Amount); await ctx.CallActivityAsync("A_SaveOrderToDatabase", order); if (total > 1000) { if (!ctx.IsReplaying) { log.LogWarning($"Need approval for {ctx.InstanceId}"); } ctx.SetCustomStatus("Needs approval"); await ctx.CallActivityAsync("A_RequestOrderApproval", order); var approvalResult = await ctx.WaitForExternalEvent <string>("OrderApprovalResult", TimeSpan.FromSeconds(180), null); ctx.SetCustomStatus(""); // clear the needs approval flag if (approvalResult != "Approved") { // timed out or got a rejected if (!ctx.IsReplaying) { log.LogWarning($"Not approved [{approvalResult}]"); } await ctx.CallActivityAsync("A_SendNotApprovedEmail", order); return(new OrderResult { Status = "NotApproved" }); } } string[] downloads = null; try { // create files in parallel var tasks = new List <Task <string> >(); foreach (var item in order.Items) { tasks.Add(ctx.CallActivityAsync <string>("A_CreatePersonalizedPdf", (order, item))); } downloads = await Task.WhenAll(tasks); } catch (Exception ex) { if (!ctx.IsReplaying) { log.LogError($"Failed to create files", ex); } } if (downloads != null) { await ctx.CallActivityWithRetryAsync("A_SendOrderConfirmationEmail", new RetryOptions(TimeSpan.FromSeconds(30), 3), (order, downloads)); return(new OrderResult { Status = "Success", Downloads = downloads }); } await ctx.CallActivityWithRetryAsync("A_SendProblemEmail", new RetryOptions(TimeSpan.FromSeconds(30), 3), order); return(new OrderResult { Status = "Problem" }); }
public static async Task <List <string> > E1_HelloSequenceWithSuborchestrator( [OrchestrationTrigger] DurableOrchestrationContextBase context) { Task <dynamic> cancellationTask = context.WaitForExternalEvent <dynamic>("CancelSequence"); var outputs = new List <string>(); //context.GetInput(); await context.CallActivityAsync("SignalRAddUserToGroup", null); // STEP 1 var step1 = context.CallSubOrchestratorAsync <SubOrchestratorExampleOutput>("SubOrchestratorExample", new SubOrchestratorExampleModel { Input = "Seattle", Progress = 20 }); Task winner = await Task.WhenAny(cancellationTask, step1); if (winner == cancellationTask) { var x = cancellationTask.Result; outputs.Add("Canceled during step 1"); await context.CallActivityAsync <string>("SendSignalRMessageActivity", new SignalRDto { id = context.InstanceId, message = $"Result: {String.Join(" ", outputs)}", progress = 100 }); return(outputs); } outputs.Add(step1.Result.Message); // STEP 2 var step2 = context.CallSubOrchestratorAsync <SubOrchestratorExampleOutput>("SubOrchestratorExample", new SubOrchestratorExampleModel { Input = "Utrecht", Progress = 40 }); winner = await Task.WhenAny(cancellationTask, step2); if (winner == cancellationTask) { outputs.Add("Canceled during step 2"); await context.CallActivityAsync <string>("SendSignalRMessageActivity", new SignalRDto { id = context.InstanceId, message = $"Result: {String.Join(" ", outputs)}", progress = 100 }); return(outputs); } outputs.Add(step2.Result.Message); // STEP 3 var step3 = context.CallSubOrchestratorAsync <SubOrchestratorExampleOutput>("SubOrchestratorExample", new SubOrchestratorExampleModel { Input = "Future Tech", Progress = 60 }); winner = await Task.WhenAny(cancellationTask, step3); if (winner == cancellationTask) { outputs.Add("Canceled during step 3"); await context.CallActivityAsync <string>("SendSignalRMessageActivity", new SignalRDto { id = context.InstanceId, message = $"Result: {String.Join(" ", outputs)}", progress = 100 }); return(outputs); } outputs.Add(step3.Result.Message); await context.CallActivityAsync <string>("SendSignalRMessageActivity", new SignalRDto { id = context.InstanceId, message = $"Result: {String.Join(" ", outputs)}", progress = 100 }); return(outputs); }
public static async Task DurableFunctionWithExternalEvent( [OrchestrationTrigger] DurableOrchestrationContextBase context) { await context.WaitForExternalEvent(ExternalEventName); }
public static async Task DurableFunctionWithExternalEventTimeout( [OrchestrationTrigger] DurableOrchestrationContextBase context) { var timeout = context.GetInput <TimeSpan>(); await context.WaitForExternalEvent(ExternalEventName, timeout); }