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);
                }
            }
        }
예제 #6
0
        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);
        }
예제 #8
0
        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++;
            }
        }
예제 #9
0
        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);
        }
예제 #12
0
        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}");
                }
            }
        }
예제 #13
0
    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);
        }
예제 #17
0
        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);
            }
        }
예제 #18
0
        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");
        }
예제 #19
0
        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);
        }
예제 #20
0
        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();
        }
예제 #23
0
        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);
            }
        }
예제 #24
0
        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}.");
        }
예제 #25
0
        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}.");
        }
예제 #27
0
        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);
        }
예제 #28
0
        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
            }
        }
예제 #29
0
        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 });
        }
예제 #30
0
        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");
        }