public async Task Run( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { await context.CreateTimer( context.CurrentUtcDateTime.AddHours(1), CancellationToken.None); context.ContinueAsNew(null); }
public static async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { string task = context.GetInput <string>(); DateTime fireAt = context.CurrentUtcDateTime.AddHours(24); await context.CreateTimer(fireAt, CancellationToken.None); await context.CallActivityAsync("SendSMS", task); }
public static async Task <bool> Run( [OrchestrationTrigger] IDurableOrchestrationContext context) { string phoneNumber = context.GetInput <string>(); if (string.IsNullOrEmpty(phoneNumber)) { throw new ArgumentNullException( nameof(phoneNumber), "A phone number input is required."); } int challengeCode = await context.CallActivityAsync <int>( "E4_SendSmsChallenge", phoneNumber); using (var timeoutCts = new CancellationTokenSource()) { // The user has 90 seconds to respond with the code they received in the SMS message. DateTime expiration = context.CurrentUtcDateTime.AddSeconds(90); Task timeoutTask = context.CreateTimer(expiration, timeoutCts.Token); bool authorized = false; for (int retryCount = 0; retryCount <= 3; retryCount++) { Task <int> challengeResponseTask = context.WaitForExternalEvent <int>("SmsChallengeResponse"); Task winner = await Task.WhenAny(challengeResponseTask, timeoutTask); if (winner == challengeResponseTask) { // We got back a response! Compare it to the challenge code. if (challengeResponseTask.Result == challengeCode) { authorized = true; break; } } else { // Timeout expired break; } } if (!timeoutTask.IsCompleted) { // All pending timers must be complete or canceled before the function exits. timeoutCts.Cancel(); } return(authorized); } }
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext monitorContext, ILogger log) { MonitorRequest input = monitorContext.GetInput <MonitorRequest>(); if (!monitorContext.IsReplaying) { log.LogInformation($"Received monitor request. Location: {input?.Location}. Phone: {input?.Phone}."); } VerifyRequest(input); DateTime endTime = monitorContext.CurrentUtcDateTime.AddHours(6); if (!monitorContext.IsReplaying) { log.LogInformation($"Instantiating monitor for {input.Location}. Expires: {endTime}."); } while (monitorContext.CurrentUtcDateTime < endTime) { // Check the weather if (!monitorContext.IsReplaying) { log.LogInformation($"Checking current weather conditions for {input.Location} at {monitorContext.CurrentUtcDateTime}."); } bool isClear = await monitorContext.CallActivityAsync <bool>("E3_GetIsClear", input.Location); if (isClear) { // It's not raining! Or snowing. Or misting. Tell our user to take advantage of it. if (!monitorContext.IsReplaying) { log.LogInformation($"Detected clear weather for {input.Location}. Notifying {input.Phone}."); } await monitorContext.CallActivityAsync("E3_SendGoodWeatherAlert", input.Phone); break; } else { // Wait for the next checkpoint var nextCheckpoint = monitorContext.CurrentUtcDateTime.AddMinutes(30); if (!monitorContext.IsReplaying) { log.LogInformation($"Next check for {input.Location} at {nextCheckpoint}."); } await monitorContext.CreateTimer(nextCheckpoint, CancellationToken.None); } } log.LogInformation($"Monitor expiring."); }
public async Task OrderPlacedOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { log = context.CreateReplaySafeLogger(log); //to prevent logging at the time of function replay Order order = context.GetInput <Order>(); try { await context.CallActivityAsync("UpsertOrder", order); await context.CallActivityAsync("NotifyRestaurant", order); Uri uri = new Uri($"{_configuration["HostEndpoint"]}/orders/accepted/{order.Id}"); await context.CallHttpAsync(HttpMethod.Get, uri); using (var cts = new CancellationTokenSource()) { var timeoutAt = context.CurrentUtcDateTime.AddSeconds(60); var timeoutTask = context.CreateTimer(timeoutAt, cts.Token); var acknowledgeTask = context.WaitForExternalEvent(Constants.RESTAURANT_ORDER_ACCEPT_EVENT); var winner = await Task.WhenAny(acknowledgeTask, timeoutTask); if (winner == acknowledgeTask) { string instanceId = $"{order.Id}-accepted"; context.StartNewOrchestration("OrderAcceptedOrchestrator", order, instanceId); cts.Cancel(); } else { //TODO: Handle time out logic log.LogError($"OrderPlacedOrchestrator Timed out {order.Id}"); await context.CallActivityAsync("NotifyCustomer", order); await context.CallActivityAsync("NotifyRestaurant", order); } } } catch (Exception ex) { if (order != null) { ex.LogExceptionDetails(log, order.Id, GetType().FullName); } else { ex.LogExceptionDetails(log, null, GetType().FullName); } } }
public async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var message = context.GetInput <SlackMessage>(); var luisResponse = await context.CallActivityAsync <LuisResponse>(nameof(Scheduler) + "_" + nameof(LuisDetectDateTime), message.Text); await context.CreateTimer(luisResponse.DetectedDateTime, CancellationToken.None); var reminderMessage = $"You scheduled \"{message.Text.Replace(luisResponse.DateTimeToken, "")}\" to happen now"; await context.CallActivityAsync(nameof(Scheduler) + "_" + nameof(PostSlackMessage), reminderMessage); }
protected virtual async Task <Status> handleTelemetrySync(IDurableOrchestrationContext context, ILogger log, StateActionContext stateCtxt) { var synced = Status.GeneralError; // Max telemetry sync cycle var operationTimeoutTime = context.CurrentUtcDateTime.AddMinutes(30); if (!context.IsReplaying) { log.LogInformation($"Instantiating telemtry sync loop for: {stateCtxt.ToJSON()}"); } while (context.CurrentUtcDateTime < operationTimeoutTime) { if (!context.IsReplaying) { log.LogInformation($"Waiting for telemetry sync for: {stateCtxt.ToJSON()}"); } synced = await context.CallActivityAsync <Status>("TelemetrySyncOrchestration_Sync", stateCtxt); if (!synced) { if (!context.IsReplaying) { log.LogInformation($"Error durring sync process: {synced.ToJSON()}"); } // TODO: Need to call another activity to set the State.Telemetry.Enabled = false to keep it in sync, maybe set an error message break; } else { var refreshRate = synced.Metadata.ContainsKey("RefreshRate") ? synced.Metadata["RefreshRate"].ToString().As <int>() : 30; // Wait for the next checkpoint var nextCheckpoint = context.CurrentUtcDateTime.AddSeconds(refreshRate); if (!context.IsReplaying) { log.LogInformation($"Continuing telemtry sync at {nextCheckpoint} for: {stateCtxt.ToJSON()}"); } await context.CreateTimer(nextCheckpoint, CancellationToken.None); } } await context.CallActivityAsync <Status>("TelemetrySyncOrchestration_SetTimeout", stateCtxt); synced = await context.CallActivityAsync <Status>("TelemetrySyncOrchestration_Sync", stateCtxt); return(synced); }
public static async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext ctx, ILogger log) { var delayTimeSpan = ctx.GetInput <TimeSpan>(); var maxRetries = 10; var count = 0; // The following loop will execute for as long as the garage door remains open // up to max number of retries. while (true) { DateTime timer = ctx.CurrentUtcDateTime.Add(delayTimeSpan); log.LogInformation($"Setting timer to expire at {timer.ToLocalTime()}"); await ctx.CreateTimer(timer, CancellationToken.None); log.LogInformation("Timer fired!"); try { using (await ctx.LockAsync(EntityId)) { log.LogInformation("Entity lock acquired."); var currentState = await ctx.CallEntityAsync <string>(EntityId, "read", null); log.LogInformation($"Current state is {currentState}."); // If the door is closed already, then don't do anything. if (currentState.ToLowerInvariant() == "closed") { log.LogInformation("Looks like the door was already closed. Will skip sending text message."); break; } await ctx.CallActivityAsync("SendTextMessage", null); } } catch (LockingRulesViolationException ex) { log.LogError(ex, "Failed to lock/call the entity."); } catch (Exception ex) { log.LogError(ex, "Unexpected exception occurred."); } if (count >= maxRetries) { log.LogInformation("Reached max retry count, but the garage door is still open. Will stop checking now."); break; } log.LogInformation("Door is still open. Will schedule another timer to check again."); count++; } }
public static async Task <bool> Run([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { var hostId = context.GetInput <EntityId>(); logger = context.CreateReplaySafeLogger(logger); var state = await context.CallActivityAsync <EntityStateResponse <HostEntity> >(nameof(GetHostState), hostId); if (!state.EntityExists) { logger.LogError("Attempted to start watch dog for a non-existing host entity: {hostId}", hostId); throw new Exception("Failed to start watch dog for non-existing entity"); } if (context.InstanceId != HostEntity.calculateHash(state.EntityState.IpAddress)) { throw new Exception("violent suicide committed on watchdog!"); } if (state.EntityState.ipv4Support || state.EntityState.ipv6Support) { context.SignalEntity(HostList.Id, HostList.AddHost, hostId); logger.LogInformation("Adding {hostId} to active hosts", hostId); } else { context.SignalEntity(HostList.Id, HostList.RemoveHost, hostId); logger.LogInformation("Removing {hostId} from active hosts", hostId); } var nextCheck = state.EntityState.DnsUptime switch { { } v when v < 0.2m => TimeSpan.FromDays(1), { } v when v >= 0.2m && v < 0.75m => TimeSpan.FromHours(12 + new Random().Next(-1, 1)), { } v when v >= 0.75m => TimeSpan.FromMinutes(60 + new Random().Next(-5, 5)), _ => TimeSpan.FromHours(1) }; #if DEBUG nextCheck = TimeSpan.FromMinutes(5); #endif await context.CreateTimer(context.CurrentUtcDateTime + nextCheck, CancellationToken.None); var host = context.CreateEntityProxy <IHostEntity>(hostId); await host.CheckUp(); context.ContinueAsNew(hostId); return(true); } }
public static async Task SetStatus([OrchestrationTrigger] IDurableOrchestrationContext ctx) { for (int i = 0; i < 3; i++) { object newStatus = await ctx.WaitForExternalEvent <object>("UpdateStatus"); ctx.SetCustomStatus(newStatus); } // Make sure status updates can survive awaits await ctx.CreateTimer(ctx.CurrentUtcDateTime.AddSeconds(2), CancellationToken.None); }
public async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { await context.CreateTimer(context.CurrentUtcDateTime + new TimeSpan(0, 0, Conf.Timeout), CancellationToken.None); var outputs = new List <string> { await context.CallActivityAsync <string>("MyOrchestratorFunction_PrintThis", Conf.Endpoint) }; return(outputs); }
public static async Task Run( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { log.LogInformation($"[START ORCHESTRATOR] --> {FunctionNames.OrderWorkflowFunction}"); var order = context.GetInput <Order>(); log.LogTrace($"Adding Order {order}"); var addResult = await context.CallActivityWithRetryAsync <bool>(FunctionNames.AddOrderFunction, new RetryOptions(TimeSpan.FromSeconds(1), 10), order); if (addResult) { DateTime orderDeadline = GetOrderDeadLine(context); var orderPaidEvent = context.WaitForExternalEvent(Events.OrderPaid); var orderCancelledEvent = context.WaitForExternalEvent(Events.OrderCancelled); var cancelTimer = context.CreateTimer(orderDeadline, CancellationToken.None); var taskCompleted = await Task.WhenAny(orderPaidEvent, orderCancelledEvent, cancelTimer); if (taskCompleted == orderCancelledEvent || taskCompleted == cancelTimer) { log.LogWarning($"Order Cancelled : {order}"); order = await context.CallActivityAsync <Order>(FunctionNames.FinalizeOrderFunction, new OrderStateChange() { NewOrderState = OrderStatus.Cancelled, OrderId = order.Id }); } else if (taskCompleted == orderPaidEvent) { log.LogTrace($"Order Paid : {order}"); order = await context.CallActivityAsync <Order>(FunctionNames.FinalizeOrderFunction, new OrderStateChange() { NewOrderState = OrderStatus.Paid, OrderId = order.Id }); await context.CallActivityAsync <string>(FunctionNames.GenerateInvoiceFunction, order); } if (order != null) { var sendMailResult = await context.CallActivityAsync <bool>(FunctionNames.SendMailFunction, order); log.LogTrace($"Sendmail result : {sendMailResult}"); } } }
public static async Task ContinueAsNew(this IDurableOrchestrationContext orchestration, object input, TimeSpan delay, bool preserveUnprocessedEvents = false) { if (orchestration is null) { throw new ArgumentNullException(nameof(orchestration)); } await orchestration .CreateTimer(delay) .ConfigureAwait(true); orchestration.ContinueAsNew(input, preserveUnprocessedEvents); }
public static async Task <IActionResult> RunOrchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var message = context.GetInput <string>(); var startAt = await context.CallActivityAsync <DateTime>("GetDateFromMessage", message); await context.CallActivityAsync("SendSlackMessage", $"*{message}* has been scheduled for *{startAt}*"); await context.CreateTimer(startAt, CancellationToken.None); await context.CallActivityAsync("SendSlackMessage", $"*{message}* to happen now."); return(new OkObjectResult(message)); }
public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) { var dnsNames = context.GetInput <string[]>(); var certificateName = dnsNames[0].Replace("*", "wildcard").Replace(".", "-"); var activity = context.CreateActivityProxy <ISharedActivity>(); // 前提条件をチェック await activity.Dns01Precondition(dnsNames); // 新しく ACME Order を作成する var orderDetails = await activity.Order(dnsNames); // 既に確認済みの場合は Challenge をスキップする if (orderDetails.Payload.Status != "ready") { // ACME Challenge を実行 var(challengeResults, propagationSeconds) = await activity.Dns01Authorization(orderDetails.Payload.Authorizations); // DNS Provider が指定した分だけ遅延させる await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(propagationSeconds), CancellationToken.None); // DNS で正しくレコードが引けるか確認 await activity.CheckDnsChallenge(challengeResults); // ACME Answer を実行 await activity.AnswerChallenges(challengeResults); // Order のステータスが ready になるまで 60 秒待機 await activity.CheckIsReady((orderDetails, challengeResults)); // 作成した DNS レコードを削除 await activity.CleanupDnsChallenge(challengeResults); } // Key Vault で CSR を作成し Finalize を実行 orderDetails = await activity.FinalizeOrder((certificateName, dnsNames, orderDetails)); // Finalize の時点でステータスが valid の時点はスキップ if (orderDetails.Payload.Status != "valid") { // Finalize 後のステータスが valid になるまで 60 秒待機 await activity.CheckIsValid(orderDetails); } // 証明書をダウンロードし Key Vault に保存 var certificate = await activity.MergeCertificate((certificateName, orderDetails)); // 証明書の更新が完了後に Webhook を送信する await activity.SendCompletedEvent((certificate.Name, certificate.ExpiresOn, dnsNames)); }
public static async Task <EmailConfirmationInfo> Orchestrator_SendEmailConfirmation( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { if (!context.IsReplaying) { log.LogInformation("SendEmailConfirmation orchestration started."); } EmailConfirmationInput input = context.GetInput <EmailConfirmationInput>(); var confirmationInfo = new EmailConfirmationInfo { Id = context.NewGuid(), RequestUri = input.RequestUri, Email = input.Email, OrchestrationId = context.InstanceId, Result = "Sent" }; await context.CallActivityAsync(nameof(Activity_SendEmailConfirmation), confirmationInfo); using (var cts = new CancellationTokenSource()) { DateTime timeoutAt = context.CurrentUtcDateTime.AddSeconds(30); Task timeoutTask = context.CreateTimer(timeoutAt, cts.Token); Task <string> confirmResultTask = context.WaitForExternalEvent <string>(_eventName); if (!context.IsReplaying) { context.SetCustomStatus($"Waiting for human interaction or timeout at: {timeoutAt.ToString("hh:mm:ss")} UTC."); } Task winnerTask = await Task.WhenAny(confirmResultTask, timeoutTask); if (winnerTask == confirmResultTask) { cts.Cancel(); confirmationInfo.Result = confirmResultTask.Result; } else { confirmationInfo.Result = "Timed Out"; } } await context.CallActivityAsync(nameof(Activity_SaveEmailConfirmationResult), confirmationInfo); return(confirmationInfo); }
public static async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { logger = context.CreateReplaySafeLogger(logger); var expiration = context.GetInput <DateTime>(); var minDelay = TimeSpan.FromSeconds(10); var maxDelay = TimeSpan.FromSeconds(30); var delayDelta = expiration - context.CurrentUtcDateTime; var waitTime = TimeSpan.FromSeconds(Math.Clamp(delayDelta.TotalSeconds, minDelay.TotalSeconds, maxDelay.TotalSeconds)); var wakeupTime = context.CurrentUtcDateTime + waitTime; logger.LogInformation($">>>>>> [ORC] Orchestration begins with expiration at { expiration }, waitTime { waitTime }, next wakeup at { wakeupTime }"); using (var cts = new CancellationTokenSource()) { var timerTask = context.CreateTimer(wakeupTime, cts.Token); var dataTask = context.WaitForExternalEvent <string>(DataEventName); var winner = await Task.WhenAny(dataTask, timerTask); if (winner == dataTask) { cts.Cancel(); var data = await dataTask; logger.LogInformation($">>>>>> [ORC] Data Event Triggered, data = { data }"); var result = await context.CallActivityAsync <string>(nameof(SayHello), data); logger.LogInformation($">>>>>> [ORC] Activity result { result }"); } else { logger.LogInformation(">>>>>> [ORC] Timer Triggered"); if (context.CurrentUtcDateTime >= expiration) { logger.LogInformation(">>>>>> [ORC] Orchestration expired"); return; } } logger.LogInformation(">>>>>> [ORC] Restarting for another round"); context.ContinueAsNew(expiration, true); } }
public static async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { logger.LogInformation("Starting cache manager"); var cacheId = context.GetInput <EntityId>(); await context.CreateTimer(context.CurrentUtcDateTime.AddMinutes(1), CancellationToken.None); logger.LogInformation($"Cleaning {cacheId.EntityKey}"); //await context.CallEntityAsync<ICache<byte[]>>(cacheId, "Clear"); context.SignalEntity(cacheId, "Clear"); }
public static async Task <bool> RegistryOrchestration( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { log.LogInformation("New orchestration started."); // this has side-effects (creating a new list) so it is // wrapped in an Activity task await context.CallActivityAsync(nameof(NewList), context.InstanceId); bool closedByUser = false; using (var timeoutCts = new CancellationTokenSource()) { // 5 minutes to fill the registry var dueTime = context.CurrentUtcDateTime .Add(TimeSpan.FromMinutes(5)); // waiting for close ("Finish") var approvalEvent = context.WaitForExternalEvent <bool>(CLOSE_TASK); log.LogInformation($"Now: {context.CurrentUtcDateTime} Timeout: {dueTime}"); // create the timeout var durableTimeout = context.CreateTimer(dueTime, timeoutCts.Token); // wait for whatever comes first: close event or 5 minute timeout var winner = await Task.WhenAny(approvalEvent, durableTimeout); // got here due to close event if (winner == approvalEvent && approvalEvent.Result) { // timer not needed timeoutCts.Cancel(); log.LogInformation("List {id} closed by timeout.", context.InstanceId); closedByUser = true; } else { // got here due to timeout log.LogInformation("List {id} time is up!", context.InstanceId); } } log.LogInformation("Workflow ended. Closed by user = {status}", closedByUser); return(closedByUser); }
public static async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var message = JObject.Parse(context.GetInput <string>()); var maxRetryNumber = (int)message[MessagePropertyNames.MaxRetryNumber]; var renewalIntervalInSeconds = (int)message[MessagePropertyNames.RenewalIntervalInSeconds]; var contextInstanceId = context.InstanceId; log.LogInformation($"ID '{contextInstanceId}': Iteration {message[MessagePropertyNames.RetryCount]}/{maxRetryNumber} started."); DateTime deadline = context.CurrentUtcDateTime.Add(TimeSpan.FromSeconds(renewalIntervalInSeconds)); using (var cts = new CancellationTokenSource()) { Task terminationTask = context.WaitForExternalEvent(TerminationEventName); Task timeoutTask = context.CreateTimer(deadline, cts.Token); Task winner = await Task.WhenAny(terminationTask, timeoutTask); if (winner == terminationTask) { // success case log.LogInformation($"ID '{contextInstanceId}': Lock-handling stopped by using instance."); cts.Cancel(); } else if ((int)message[MessagePropertyNames.RetryCount] < maxRetryNumber) { // timeout case log.LogInformation($"ID '{contextInstanceId}': Interval reached for lock-renewal."); (bool terminated, string nextMessageJson) = await context.CallActivityAsync <(bool, string)>(nameof(RenewLockActivity), (contextInstanceId, message)); if (!terminated) { log.LogInformation($"ID '{contextInstanceId}': Scheduling next iteration."); context.ContinueAsNew(nextMessageJson); } } else { log.LogInformation($"ID '{contextInstanceId}': Maximal number of cycles reached. Aborting lock-handling."); } } }
public static async Task RunOrchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { log.LogInformation($"************** RunOrchestrator method executing ********************"); // Using tuples but could also define a class for this data var(descontoRequest, requestUri) = context.GetInput <Tuple <DescontoRequest, Uri> >(); var moderationRequest = new DescontoModeracaoRequest { DescontoRequest = descontoRequest, ApproveRequestUrl = $"{requestUri.Scheme}://{requestUri.Host}:{requestUri.Port}/api/HumanPatternExample_Approve?id={context.InstanceId}", DeclineRequestUrl = $"{requestUri.Scheme}://{requestUri.Host}:{requestUri.Port}/api/HumanPatternExample_Decline?id={context.InstanceId}", }; await context.CallActivityAsync("HumanPatternExample_RequestApproval", moderationRequest); using (var timeout = new CancellationTokenSource()) // Defino o Timeout para aprovação do workflow { DateTime moderationDeadline = context.CurrentUtcDateTime.AddSeconds(10); Task durableTimeout = context.CreateTimer(moderationDeadline, timeout.Token); Task <bool> moderatedEvent = context.WaitForExternalEvent <bool>("Moderation"); if (moderatedEvent == await Task.WhenAny(moderatedEvent, durableTimeout)) { timeout.Cancel(); bool isApproved = moderatedEvent.Result; if (isApproved) { log.LogInformation($"************** Desconto de { descontoRequest.ValorDesconto } aprovado com sucesso. ********************"); //CRIAR REGRA DE NEGOCIO PARA APROVAR } else { log.LogInformation($"************** Desconto de { descontoRequest.ValorDesconto } reprovado. ********************"); //CRIAR REGRA DE NEGOCIO PARA NEGAR DESCONTO } } else { log.LogInformation($"************** Desconto de { descontoRequest.ValorDesconto } não recebeu intervenção... ********************"); //CRIAR REGRA DE NEGOCIO QUANDO NAO RECEBER INTERVENCAO } } log.LogInformation($"************** Orchestration complete ********************"); }
public static async Task StartComputeSetOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { log = context.CreateReplaySafeLogger(log); var computeSetId = context.GetInput <string>(); log.LogWarning("*** {eventName}: {computeSetId}", "ComputeSetStarting", computeSetId); // pretend to start compute set await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(5), CancellationToken.None); var computeSet = context.CreateEntityProxy <IComputeSet>(new EntityId(nameof(ComputeSet), computeSetId)); await computeSet.SignalComputeSetStarted(); }
public async Task Periodic_Cleanup_Loop( [OrchestrationTrigger] IDurableOrchestrationContext context) { var expire = context.GetInput <Expire>(); await context.CallActivityAsync(nameof(this.CleanUpNotification), "CleanUp!"); DateTime nextCleanup = context.CurrentUtcDateTime.AddSeconds(10); if (expire.Value > nextCleanup) { await context.CreateTimer(nextCleanup, CancellationToken.None); context.ContinueAsNew(expire); } }
public static async Task CreditConfirmationWorkflow( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { var operation = context.GetInput <CreditOperation>(); logger.LogInformation("Start of customer credit confirmation workflow for operation", operation.Identifier); await context.CallActivityAsync(nameof(ConsoleFunctions.AddToQueue), $"Account {operation.Account} now has {Global.ExpirationMinutes} minutes to confirm the {operation.Identifier} operation."); using (var timeoutCts = new CancellationTokenSource()) { var dueTime = context.CurrentUtcDateTime .Add(TimeSpan.FromMinutes(Global.ExpirationMinutes)); var confirmationEvent = context.WaitForExternalEvent <bool>(CONFIRM_TASK); logger.LogInformation($"Now: {context.CurrentUtcDateTime} Timeout: {dueTime}"); var durableTimeout = context.CreateTimer(dueTime, timeoutCts.Token); var confirmed = await Task.WhenAny(confirmationEvent, durableTimeout); if (confirmed == confirmationEvent && confirmationEvent.Result) { timeoutCts.Cancel(); logger.LogInformation("Account {account} confirmed the operation {operation}.", operation.Account, operation.Identifier); await context.CallActivityAsync(nameof(ConsoleFunctions.AddToQueue), $"Account {operation.Account} confirmed the operation {operation.Identifier}!"); // await context.CallActivityAsync(nameof(Global.StartNewWorkflow), // ((nameof(NewUserSequentialFunctions.RunUserSequentialWorkflow), // username))); } else { logger.LogInformation("Operation {operation} confirmation timed out.", operation.Identifier); await context.CallActivityAsync(nameof(ConsoleFunctions.AddToQueue), $"Operation {operation.Identifier} confirmation timed out."); await context.CallActivityAsync(nameof(MakeCreditOperationExpired), operation); } } await context.CallActivityAsync(nameof(ConsoleFunctions.AddToQueue), $"Account {operation.Account} confirmation workflow complete for operation {operation.Identifier}."); }
public async Task <bool> ManuallyApproveRecognition([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { // Get speed violation data from orchestration context var sv = context.GetInput <SpeedViolation>(); // Call activity that sends approval request to Slack. Note that this // activity will not await the human's response. It will only wait until // message will have been sent to Slack. await context.CallActivityAsync(nameof(SendApprovalRequestViaSlack), new ApprovalRequest { OrchestrationInstanceID = context.InstanceId, SpeedViolation = sv }); // We want the human operator to respond within 60 minutes. We setup a // timer for that. Note that this is NOT a regular .NET timer. It is a // special timer from the Durable Functions runtime! using var timeoutCts = new CancellationTokenSource(); var expiration = context.CurrentUtcDateTime.AddMinutes(60); var timeoutTask = context.CreateTimer(expiration, timeoutCts.Token); // Wait for the event that will be raised once we have received the response from Slack. var approvalResponse = context.WaitForExternalEvent <bool>(ReceiveApprovalResponseEvent); // Wait for Slack response or timer, whichever comes first var winner = await Task.WhenAny(approvalResponse, timeoutTask); // Was the Slack task the first task to complete? if (winner == approvalResponse && approvalResponse.Result) { // License plate read approved -> Store speed violation // await context.CallActivityAsync(nameof(StoreSpeedViolation), sv); var entityId = Guid.NewGuid(); var lawsuitId = new EntityId(nameof(SpeedViolationLawsuit), entityId.ToString()); await context.CallEntityAsync(lawsuitId, nameof(SpeedViolationLawsuit.SetSpeedViolation), sv); log.LogInformation(entityId.ToString()); } if (!timeoutTask.IsCompleted) { // All pending timers must be completed or cancelled before the function exits. timeoutCts.Cancel(); } return(winner == approvalResponse && approvalResponse.Result); }
public static async Task UserConfirmationWorkflow( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { var username = context.GetInput <string>(); logger.LogInformation("Start of user confirmation workflow for {user}", username); await context.CallActivityAsync(nameof(ConsoleFunctions.AddToQueue), $"User {username} now has {Global.ExpirationMinutes} minutes to confirm they are ready."); using (var timeoutCts = new CancellationTokenSource()) { var dueTime = context.CurrentUtcDateTime .Add(TimeSpan.FromMinutes(Global.ExpirationMinutes)); var approvalEvent = context.WaitForExternalEvent <bool>(APPROVAL_TASK); logger.LogInformation($"Now: {context.CurrentUtcDateTime} Timeout: {dueTime}"); var durableTimeout = context.CreateTimer(dueTime, timeoutCts.Token); var winner = await Task.WhenAny(approvalEvent, durableTimeout); if (winner == approvalEvent && approvalEvent.Result) { timeoutCts.Cancel(); logger.LogInformation("User {user} confirmed.", username); await context.CallActivityAsync(nameof(ConsoleFunctions.AddToQueue), $"{username} has accepted the challenge!."); await context.CallActivityAsync(nameof(Global.StartNewWorkflow), ((nameof(NewUserSequentialFunctions.RunUserSequentialWorkflow), username))); } else { logger.LogInformation("User {user} confirmation timed out.", username); await context.CallActivityAsync(nameof(ConsoleFunctions.AddToQueue), $"User {username} failed to confirm in time."); await context.CallActivityAsync(nameof(KillUser), username); } } await context.CallActivityAsync(nameof(ConsoleFunctions.AddToQueue), $"User confirmation workflow complete for {username}."); }
public static async Task <bool> RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var req = context.GetInput <RequestModel>(); var mins = req.TimeToSoakInMinutes; var initiated = context.CurrentUtcDateTime; var scheduled = initiated.AddMinutes(mins); await context.CreateTimer(scheduled, CancellationToken.None); await context.CallActivityAsync("SchedulerActivity", req.CallbackUrl); return(true); }
public static async Task MonitorUrl( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var input = context.GetInput <AzDoRelease>(); try { await SendTaskStartedEvent(context, input); // send task started message feed and log the message. You will see feed messages in task log UI. await SendTaskLogFeeds(context, input, "Task Started"); for (var i = 1; ; i++) { var urlResponse = await context.CallHttpAsync(HttpMethod.Get, new Uri(input.WebUrl)); var logMessage = $"{DateTime.UtcNow:0} Message {i}"; await SendTaskLogFeeds(context, input, logMessage); if (urlResponse.StatusCode == HttpStatusCode.OK) { break; } else { await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(10), CancellationToken.None); } } await SendTaskCompletedEvent(context, input, TaskResultSucceeded); } catch { await SendTaskCompletedEvent(context, input, TaskResultFailed); } finally { // Create task log entry // Append task log data // Attach task log to timeline record // Set task variable } }
public async Task ThrottleVoid( [OrchestrationTrigger] IDurableOrchestrationContext context) { var input = context.GetInput <ThrottledFunctionCall>(); using var propsDisposable = context.PushLoggerProperties(); _log.Enter(LogEventLevel.Information, arguments: new object?[] { input }); var throttleProxy = context.CreateEntityProxy <IThrottleEntity>(input.ThrottleKey); var scheduleTime = await throttleProxy.GetNextScheduleTime(); await context.CreateTimer(scheduleTime.UtcDateTime, CancellationToken.None); await context.CallActivityAsync(input.Name, input.Input); _log.Exit(LogEventLevel.Information, arguments: new object?[] { input }); }
public static async Task <string> ContinueAsNew_Repro285([OrchestrationTrigger] IDurableOrchestrationContext ctx) { var input = ctx.GetInput <int>(); if (input == 0) { ctx.ContinueAsNew(1); return("continue as new"); } else if (input == 1) { await ctx.CreateTimer <object>(ctx.CurrentUtcDateTime + TimeSpan.FromSeconds(1), null, CancellationToken.None); } return("ok"); }