public async Task <bool> IsExecutionPermitted(string circuitBreakerId, ILogger log, IDurableOrchestrationContext orchestrationContext)
        {
            if (string.IsNullOrEmpty(circuitBreakerId))
            {
                throw new ArgumentNullException($"{nameof(circuitBreakerId)}");
            }

            log?.LogCircuitBreakerMessage(circuitBreakerId, $"Asking IsExecutionPermitted (consistency priority) for circuit-breaker = '{circuitBreakerId}'.");

            return(await orchestrationContext.CreateEntityProxy <IDurableCircuitBreaker>(circuitBreakerId).IsExecutionPermitted());
        }
        public static async Task RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext orchestrationContext,
            ILogger log)
        {
            if (orchestrationContext is null)
            {
                throw new ArgumentNullException(nameof(orchestrationContext));
            }

            var command       = orchestrationContext.GetInput <ICommand>();
            var commandResult = command.CreateResult();
            var commandLog    = orchestrationContext.CreateReplaySafeLogger(log ?? NullLogger.Instance);

            try
            {
                orchestrationContext.SetCustomStatus("Auditing command", log);

                await orchestrationContext
                .AuditAsync(command, commandResult)
                .ConfigureAwait(true);

                orchestrationContext.SetCustomStatus("Processing command", log);

                commandResult = await orchestrationContext
                                .CallSubOrchestratorWithRetryAsync <ICommandResult>(OrchestratorCommandOrchestrationHandler.GetCommandOrchestrationName(command), command.CommandId.ToString(), command)
                                .ConfigureAwait(true);
            }
            catch (Exception exc)
            {
                commandResult ??= command.CreateResult();
                commandResult.Errors.Add(exc);
            }
            finally
            {
                try
                {
                    orchestrationContext.SetCustomStatus("Augmenting command result", log);

                    commandResult = await orchestrationContext
                                    .CallActivityWithRetryAsync <ICommandResult>(nameof(CommandResultAugmentActivity), commandResult)
                                    .ConfigureAwait(true);
                }
                catch (Exception exc)
                {
                    commandResult ??= command.CreateResult();
                    commandResult.Errors.Add(exc);
                }

                orchestrationContext.SetCustomStatus("Auditing command result", log);

                await orchestrationContext
                .AuditAsync(command, commandResult)
                .ConfigureAwait(true);

                var commandException = commandResult.Errors?.ToException();

                if (commandException is null)
                {
                    orchestrationContext.SetCustomStatus($"Command succeeded", log);
                }
                else
                {
                    orchestrationContext.SetCustomStatus($"Command failed: {commandException.Message}", log, commandException);
                }

                orchestrationContext.SetOutput(commandResult);
            }
        }
예제 #3
0
        public static async Task RunImportOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
        {
            log.LogInformation("RunImportOrchestrator: entering");

            try {
                ImportRequest importRequest = context.GetInput <ImportRequest>();
                // Deploy the ARM template to Create empty SQL resource
                string deploymentName = await context.CallActivityAsync <string>(nameof(AzureResourceManagerActivity.BeginDeployArmTemplateForImport), importRequest);

                while (true)
                {
                    log.LogInformation("RunImportOrchestrator: starting ARM deployment");
                    string status = await context.CallActivityAsync <string>(nameof(AzureResourceManagerActivity.GetArmDeploymentForImport), (importRequest.SubscriptionId, importRequest.TargetSqlServerResourceGroupName, deploymentName));

                    if (status == "Succeeded")
                    {
                        log.LogInformation("RunImportOrchestrator: ARM deployment succeeded");
                        break;
                    }
                    else if (status == "Failed")
                    {
                        log.LogInformation("RunImportOrchestrator: ARM deployment failed");
                        throw new Exception("Failed ARM Deployment");
                    }

                    // Orchestration sleeps until this time.
                    var nextCheck = context.CurrentUtcDateTime.AddSeconds(10);

                    if (!context.IsReplaying)
                    {
                        log.LogInformation($"RunImportOrchestrator: Replaying ARM deployment, next check at {nextCheck}.");
                    }
                    await context.CreateTimer(nextCheck, CancellationToken.None);
                }

                log.LogInformation("RunImportOrchestrator: Enumerating databases");
                var databases = await context.CallActivityAsync <dynamic>(nameof(AzureResourceManagerActivity.GetArmTemplateForImportSkipParameterization), importRequest);

                // Create BatchPool And Job
                log.LogInformation("RunImportOrchestrator: Creating batch pool and import job");
                string jobId = await context.CallActivityAsync <string>(nameof(BatchActivity.CreateBatchPoolAndImportJob), importRequest);

                string containerUrl = await context.CallActivityAsync <string>(nameof(StorageActivity.GettingJobContainerUrl), (importRequest.SubscriptionId, importRequest.ResourceGroupName, importRequest.StorageAccountName, importRequest.ContainerName));

                log.LogInformation("RunImportOrchestrator: Creating import database tasks");
                BatchActivity.CreateBatchTasks("Import", jobId, containerUrl, importRequest.BatchAccountUrl, importRequest.TargetSqlServerName, importRequest.TargetAccessToken, databases, log);

                // create output values
                Tuple <string, string>[] outputValues =
                {
                    Tuple.Create("Orchestration progress:", "Complete"),
                    Tuple.Create("deploymentName",          deploymentName),
                    Tuple.Create("jobId",                   jobId),
                    Tuple.Create("containerUrl",            containerUrl)
                };
                context.SetOutput(outputValues);
            }
            finally {
                log.LogInformation("RunImportOrchestrator: exiting");
            }
        }
예제 #4
0
        public static async Task <IActionResult> DonateLocation(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            [SignalR(HubName = "center")] IAsyncCollector <SignalRMessage> signalRMessages,
            [Table(nameof(Center))] CloudTable centerTable,
            ILogger log)
        {
            var twilioResponse  = context.GetInput <TwilioResponse>();
            var centerClient    = new DataAccess <Center>(centerTable);
            var msgProcessed    = true;
            var responseMessage = "";

            try
            {
                var centerFilter = new TableQuery <Center>()
                                   .Where(TableQuery.GenerateFilterCondition("HostPhoneNumber", QueryComparisons.Equal,
                                                                             twilioResponse.From));
                var centers = await centerClient.GetAllAsync(centerFilter);

                var center      = centers.FirstOrDefault();
                var donatedItem = ConfigUtil.GetEnvironmentVariable("donatedItem");

                if (center != null)
                {
                    var geoAddress = await GetLocationAsync(twilioResponse.Body);

                    if (geoAddress.results.Length > 0)
                    {
                        var address = geoAddress.results.FirstOrDefault();
                        if (string.IsNullOrEmpty(center.DonationPhoneNumber))
                        {
                            var areaCode        = int.Parse(twilioResponse.From.Substring(1, 3));
                            var newTwilioNumber = TwilioUtil.GetTwilioNumber(areaCode)?.PhoneNumber?.ToString();

                            var simulated = bool.Parse(ConfigUtil.GetEnvironmentVariable("Simulated"));
                            if (!simulated)
                            {
                                var phoneSID = TwilioUtil.ProvisionNumber(newTwilioNumber);
                                center.DonationPhoneNumberSID = phoneSID;
                            }
                            center.DonationPhoneNumber = newTwilioNumber;
                        }
                        center.Address = address.formatted_address;
                        center.Active  = true;
                        center.Lat     = address.geometry.location.lat.ToString();
                        center.Lng     = address.geometry.location.lng.ToString();

                        await centerClient.ReplaceAsync(center);

                        TwilioUtil.Notify(twilioResponse.From, string.Format(Messages.DonationAddress, center.Address, donatedItem, center.DonationPhoneNumber), log);

                        var broadcastStat = new { Lat = center.Lat, Lng = center.Lng, PhoneNumber = center.DonationPhoneNumber };
                        await signalRMessages.AddAsync(
                            new SignalRMessage
                        {
                            Target    = "BroadcastMessage",
                            Arguments = new[] { broadcastStat }
                        });
                    }
                    else
                    {
                        TwilioUtil.Notify(twilioResponse.From, string.Format(Messages.DonationAddressNotFound, center.Address), log);
                    }
                }
            }
            catch (Exception ex)
            {
                msgProcessed    = false;
                responseMessage = $"{ex.Message} {ex.StackTrace} {ex?.InnerException?.StackTrace ?? ""}";
            }
            return(msgProcessed ? new OkObjectResult(msgProcessed) : (IActionResult) new BadRequestObjectResult(responseMessage));
        }
 private RecompensateApplicationProcessCommand BuildRecompensationCommand(
     IDurableOrchestrationContext context,
     RegisterApplicationCommand command)
 {
     return(new RecompensateApplicationProcessCommand(context.InstanceId, command.Photo, command.Cv));
 }
예제 #6
0
 public static Task <Project> GetProjectAsync(this IDurableOrchestrationContext durableOrchestrationContext, Guid projectId)
 => durableOrchestrationContext.CallActivityWithRetryAsync <Project>(nameof(ProjectGetActivity), projectId);
예제 #7
0
        public static async Task <ICommandResult> RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext functionContext,
            ILogger log)
        {
            if (functionContext is null)
            {
                throw new ArgumentNullException(nameof(functionContext));
            }

            var(command, provider) = functionContext.GetInput <(IProviderCommand, Provider)>();

            var commandResult   = command.CreateResult();
            var commandMessage  = default(ICommandMessage);
            var commandCallback = default(string);

            try
            {
                functionContext.SetCustomStatus($"Acquire callback url for command '{command.CommandId}'", log);

                commandCallback = await functionContext
                                  .CallActivityWithRetryAsync <string>(nameof(CallbackAcquireActivity), (functionContext.InstanceId, command))
                                  .ConfigureAwait(true);

                commandMessage = new ProviderCommandMessage(command, commandCallback);

                functionContext.SetCustomStatus($"Prepare sending command '{command.CommandId}'", log);

                await RegisterProviderAsync(functionContext, command, provider)
                .ConfigureAwait(true);

                await EnableProviderAsync(functionContext, command, provider)
                .ConfigureAwait(true);

                command = await AugmentCommandAsync(functionContext, provider, command)
                          .ConfigureAwait(true);

                await functionContext
                .AuditAsync(provider, command, commandResult)
                .ConfigureAwait(true);

                try
                {
                    functionContext.SetCustomStatus($"Sending command '{command.CommandId}'", log);

                    commandResult = await functionContext
                                    .CallActivityWithRetryAsync <ICommandResult>(nameof(CommandSendActivity), (provider, commandMessage))
                                    .ConfigureAwait(true);
                }
                catch (RetryCanceledException)
                {
                    commandResult = await functionContext
                                    .CallActivityWithRetryAsync <ICommandResult>(nameof(CommandResultActivity), (provider, commandMessage))
                                    .ConfigureAwait(true);
                }
                finally
                {
                    await functionContext
                    .AuditAsync(provider, command, commandResult)
                    .ConfigureAwait(true);
                }

                if (commandResult.RuntimeStatus.IsActive())
                {
                    var commandTimeout = (commandResult.Timeout > TimeSpan.Zero && commandResult.Timeout < CommandResult.MaximumTimeout)
                        ? commandResult.Timeout         // use the timeout reported back by the provider
                        : CommandResult.MaximumTimeout; // use the defined maximum timeout

                    functionContext.SetCustomStatus($"Waiting for command ({command.CommandId}) result on {commandCallback} for {commandTimeout}", log);

                    commandResult = await functionContext
                                    .WaitForExternalEvent <ICommandResult>(command.CommandId.ToString(), commandTimeout, null)
                                    .ConfigureAwait(true);

                    if (commandResult is null)
                    {
                        commandResult = await functionContext
                                        .CallActivityWithRetryAsync <ICommandResult>(nameof(CommandResultActivity), (provider, commandMessage))
                                        .ConfigureAwait(true);

                        throw new TimeoutException($"Provider '{provider.Id}' ran into timeout ({commandTimeout})");
                    }
                }
            }
            catch (Exception exc)
            {
                functionContext.SetCustomStatus($"Sending command '{command.CommandId}' failed: {exc.Message}", log, exc);

                // ensure we always have a command result
                // to add our exception so we won't break
                // our command auditing in the finally block

                commandResult ??= command.CreateResult();
                commandResult.Errors.Add(exc);

                // re-throw the exception to inform the
                // outer orchestration that some bad happened

                throw;
            }
            finally
            {
                if (!string.IsNullOrEmpty(commandCallback))
                {
                    functionContext.SetCustomStatus($"Invalidating callback url for command '{command.CommandId}'", log);

                    await functionContext
                    .CallActivityWithRetryAsync(nameof(CallbackInvalidateActivity), functionContext.InstanceId)
                    .ConfigureAwait(true);
                }

                await functionContext
                .AuditAsync(provider, command, commandResult)
                .ConfigureAwait(true);

                await ProcessOutputAsync(functionContext, provider, command, commandResult)
                .ConfigureAwait(true);
            }

            return(commandResult);
        }
 public static int NoOpOrchestration([OrchestrationTrigger] IDurableOrchestrationContext ctx)
 {
     return(ctx.GetInput <int>());
 }
예제 #9
0
        public static async Task RunOrchestration(
            [OrchestrationTrigger] IDurableOrchestrationContext functionContext,
            ILogger log)
        {
            if (functionContext is null)
            {
                throw new ArgumentNullException(nameof(functionContext));
            }

            if (log is null)
            {
                throw new ArgumentNullException(nameof(log));
            }

            var command       = functionContext.GetInput <OrchestratorTeamCloudUserUpdateCommand>();
            var commandResult = command.CreateResult();
            var user          = command.Payload;

            using (log.BeginCommandScope(command))
            {
                try
                {
                    functionContext.SetCustomStatus($"Updating user.", log);

                    var existingUser = default(UserDocument);

                    using (await functionContext.LockAsync <UserDocument>(user.Id.ToString()).ConfigureAwait(true))
                    {
                        existingUser = await functionContext
                                       .GetUserAsync(user.Id)
                                       .ConfigureAwait(true);

                        if (existingUser is null)
                        {
                            throw new OrchestratorCommandException($"User '{user.Id}' does not exist.", command);
                        }

                        if (user.HasEqualTeamCloudInfo(existingUser))
                        {
                            throw new OrchestratorCommandException($"User '{user.Id}' TeamCloud details have not changed.", command);
                        }

                        if (!user.HasEqualMemberships(existingUser))
                        {
                            throw new OrchestratorCommandException($"User '{user.Id}' Project Memberships cannot be changed using the TeamCloudUserUpdateCommand. Project Memebership details must be changed using the ProjectUserUpdateCommand.", command);
                        }

                        user = await functionContext
                               .SetUserTeamCloudInfoAsync(user)
                               .ConfigureAwait(true);
                    }

                    var projects = default(IEnumerable <ProjectDocument>);

                    // only update all projects if the updated user is an admin
                    // or the user was an admin before the update, otherwise
                    // only update member projects if user's teamcloud level properties changed
                    if (user.IsAdmin() || existingUser.IsAdmin())
                    {
                        projects = await functionContext
                                   .ListProjectsAsync()
                                   .ConfigureAwait(true);
                    }
                    else if (user.ProjectMemberships.Any() && !user.Properties.SequenceEqual(existingUser.Properties))
                    {
                        projects = await functionContext
                                   .ListProjectsAsync(user.ProjectMemberships.Select(m => m.ProjectId).ToList())
                                   .ConfigureAwait(true);
                    }

                    if (projects?.Any() ?? false)
                    {
                        foreach (var project in projects)
                        {
                            var projectUpdateCommand = new OrchestratorProjectUpdateCommand(command.BaseApi, command.User, project);

                            functionContext.StartNewOrchestration(nameof(OrchestratorProjectUpdateCommandOrchestration), projectUpdateCommand);
                        }
                    }

                    commandResult.Result = user;

                    functionContext.SetCustomStatus($"User updated.", log);
                }
                catch (Exception ex)
                {
                    functionContext.SetCustomStatus("Failed to update user.", log, ex);

                    commandResult ??= command.CreateResult();
                    commandResult.Errors.Add(ex);

                    throw;
                }
                finally
                {
                    functionContext.SetOutput(commandResult);
                }
            }
        }
 public async Task RenewSiteCertificates([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
 {
     var(site, certificates) = context.GetInput <(Site, Certificate[])>();
예제 #11
0
 public static Task <UserDocument> GetUserAsync(this IDurableOrchestrationContext functionContext, string userId, bool allowUnsafe = false)
 => functionContext.IsLockedBy <UserDocument>(userId) || allowUnsafe
     ? functionContext.CallActivityWithRetryAsync <UserDocument>(nameof(UserGetActivity), userId)
     : throw new NotSupportedException($"Unable to get user '{userId}' without acquired lock");
예제 #12
0
        public static async Task <string> RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            string response = "OK";

            List <DataOpParameters> pipelines = context.GetInput <List <DataOpParameters> >();

            log.LogInformation($"RunOrchestrator: Number of pipelines: {pipelines.Count}.");

            foreach (var pipe in pipelines)
            {
                context.SetCustomStatus($"Starting pipe number {pipe.Id} with name {pipe.Name}");
                if (pipe.Name == "CreateIndex")
                {
                    response = await context.CallActivityAsync <string>("ManageDataOps_CreateIndex", pipe);
                }
                else if (pipe.Name == "DataQC")
                {
                    List <QcResult> qcList = await context.CallActivityAsync <List <QcResult> >("ManageDataOps_InitDataQC", pipe);

                    var tasks = new Task <List <int> > [qcList.Count];
                    for (int i = 0; i < qcList.Count; i++)
                    {
                        int     qcId     = qcList[i].Id;
                        JObject pipeParm = JObject.Parse(pipe.JsonParameters);
                        pipeParm["RuleId"]  = qcId;
                        pipe.JsonParameters = pipeParm.ToString();
                        tasks[i]            = context.CallActivityAsync <List <int> >("ManageDataOps_DataQC", pipe);
                    }

                    await Task.WhenAll(tasks);

                    List <RuleFailures> failures = new List <RuleFailures>();
                    for (int i = 0; i < qcList.Count; i++)
                    {
                        failures.Add(new RuleFailures {
                            RuleId = qcList[i].Id, Failures = tasks[i].Result
                        });
                    }
                    DataQCDataOpsCloseParameters parms = new DataQCDataOpsCloseParameters()
                    {
                        Parameters = pipe,
                        Failures   = failures
                    };
                    log.LogInformation($"RunOrchestrator: Ready to close data QC");
                    string stat = await context.CallActivityAsync <string>("ManageDataOps_CloseDataQC", parms);
                }
                else if (pipe.Name == "DataTransfer")
                {
                    log.LogInformation($"Starting data transfer");
                    List <string> files = await context.CallActivityAsync <List <string> >("ManageDataOps_InitDataTransfer", pipe);

                    TransferParameters parms = JObject.Parse(pipe.JsonParameters).ToObject <TransferParameters>();
                    if (parms.SourceType == "DataBase")
                    {
                        foreach (string file in files)
                        {
                            JObject pipeParm = JObject.Parse(pipe.JsonParameters);
                            pipeParm["Table"]   = file;
                            pipe.JsonParameters = pipeParm.ToString();
                            string stat = await context.CallActivityAsync <string>("ManageDataOps_DeleteDataTransfer", pipe);
                        }
                    }

                    foreach (string file in files)
                    {
                        JObject pipeParm = JObject.Parse(pipe.JsonParameters);
                        pipeParm["Table"]   = file;
                        pipe.JsonParameters = pipeParm.ToString();
                        string stat = await context.CallActivityAsync <string>("ManageDataOps_DataTransfer", pipe);
                    }
                }
                else if (pipe.Name == "Predictions")
                {
                    log.LogInformation($"Starting Predictions");
                    List <PredictionCorrection> predictionList = await context.CallActivityAsync <List <PredictionCorrection> >("ManageDataOps_InitPredictions", pipe);

                    var     tasks    = new Task <string> [predictionList.Count];
                    JObject pipeParm = JObject.Parse(pipe.JsonParameters);
                    for (int i = 0; i < predictionList.Count; i++)
                    {
                        int id = predictionList[i].Id;
                        pipeParm["PredictionId"] = id;
                        pipe.JsonParameters      = pipeParm.ToString();
                        string stat = await context.CallActivityAsync <string>("ManageDataOps_Prediction", pipe);
                    }
                }
                else
                {
                    log.LogInformation($"Artifact {pipe.Name} does not exist");
                }
                context.SetCustomStatus($"Completed pipe number {pipe.Id} with name {pipe.Name}");
            }
            log.LogInformation($"RunOrchestrator: All pipelines processed");
            return(response);
        }
        public async Task <DurableCircuitBreaker> GetBreakerState(string circuitBreakerId, ILogger log, IDurableOrchestrationContext orchestrationContext)
        {
            log?.LogCircuitBreakerMessage(circuitBreakerId, $"Getting breaker state for circuit-breaker = '{circuitBreakerId}'.");

            return(await orchestrationContext.CreateEntityProxy <IDurableCircuitBreaker>(circuitBreakerId).GetBreakerState());
        }
        public async Task RecordFailure(string circuitBreakerId, ILogger log, IDurableOrchestrationContext orchestrationContext)
        {
            log?.LogCircuitBreakerMessage(circuitBreakerId, $"Recording failure for circuit-breaker = '{circuitBreakerId}'.");

            await orchestrationContext.CreateEntityProxy <IDurableCircuitBreaker>(circuitBreakerId).RecordFailure();
        }
예제 #15
0
 public static Task SetAppSettingAsync(this IDurableOrchestrationContext functionContext, string key, string value = default)
 => functionContext.CallActivityWithRetryAsync(nameof(ProviderCommandAppSettingActivity), (key, value));
 public static Task <UserDocument> SetUserProjectMembershipAsync(this IDurableOrchestrationContext functionContext, UserDocument user, string projectId, bool allowUnsafe = false)
 => functionContext.IsLockedBy <UserDocument>(user.Id) || allowUnsafe
     ? functionContext.CallActivityWithRetryAsync <UserDocument>(nameof(UserProjectMembershipSetActivity), (user, projectId))
     : throw new NotSupportedException($"Unable to create or update project membership without acquired lock for user {user.Id}");
 public OrchestrationContextProxy(IDurableOrchestrationContext context)
 {
     _context = context;
 }
예제 #18
0
        public static async Task RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            var notification = context.GetInput <NotificationDataEntity>();

            // Update notification status.
            await context.CallActivityWithRetryAsync(
                FunctionNames.UpdateNotificationStatusActivity,
                FunctionSettings.DefaultRetryOptions,
                (notification.Id, NotificationStatus.SyncingRecipients));

            // All users.
            if (notification.AllUsers)
            {
                await context.CallActivityWithRetryAsync(
                    FunctionNames.SyncAllUsersActivity,
                    FunctionSettings.DefaultRetryOptions,
                    notification);

                return;
            }

            // Members of specific teams.
            if (notification.Rosters.Any())
            {
                var tasks = new List <Task>();
                foreach (var teamId in notification.Rosters)
                {
                    var task = context.CallActivityWithRetryAsync(
                        FunctionNames.SyncTeamMembersActivity,
                        FunctionSettings.DefaultRetryOptions,
                        (notification.Id, teamId));
                    tasks.Add(task);
                }

                // Fan-Out Fan-In.
                await Task.WhenAll(tasks);

                return;
            }

            // Members of M365 groups, DG or SG.
            if (notification.Groups.Any())
            {
                var tasks = new List <Task>();
                foreach (var groupId in notification.Groups)
                {
                    var task = context.CallActivityWithRetryAsync(
                        FunctionNames.SyncGroupMembersActivity,
                        FunctionSettings.DefaultRetryOptions,
                        (notification.Id, groupId));

                    tasks.Add(task);
                }

                // Fan-Out Fan-In
                await Task.WhenAll(tasks);

                return;
            }

            // General channel of teams.
            if (notification.Teams.Any())
            {
                await context.CallActivityWithRetryAsync(
                    FunctionNames.SyncTeamsActivity,
                    FunctionSettings.DefaultRetryOptions,
                    notification);

                return;
            }

            // Invalid audience.
            var errorMessage = $"Invalid audience select for notification id: {notification.Id}";

            log.LogError(errorMessage);
            throw new ArgumentException(errorMessage);
        }
예제 #19
0
 private static void AddUploadTask(List <Task> tasks, IDurableOrchestrationContext context, BlobModel blob)
 {
     tasks.Add(context.CallActivityAsync <AnalysisResult>("UploadFunction", blob));
 }
        public async Task AddCertificate([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
        {
            var request = context.GetInput <AddCertificateRequest>();

            var activity = context.CreateActivityProxy <ISharedFunctions>();

            var site = await activity.GetSite((request.ResourceGroupName, request.AppName, request.SlotName));

            if (site == null)
            {
                log.LogError($"{request.AppName} is not found");
                return;
            }

            var hostNameSslStates = site.HostNameSslStates
                                    .Where(x => request.Domains.Contains(x.Name))
                                    .ToArray();

            if (hostNameSslStates.Length != request.Domains.Length)
            {
                foreach (var hostName in request.Domains.Except(hostNameSslStates.Select(x => x.Name)))
                {
                    log.LogError($"{hostName} is not found");
                }
                return;
            }

            // ワイルドカード、コンテナ、Linux の場合は DNS-01 を利用する
            var useDns01Auth = request.Domains.Any(x => x.StartsWith("*")) || site.Kind.Contains("container") || site.Kind.Contains("linux");

            // 前提条件をチェック
            if (useDns01Auth)
            {
                await activity.Dns01Precondition(request.Domains);
            }
            else
            {
                await activity.Http01Precondition(site);
            }

            // 新しく ACME Order を作成する
            var orderDetails = await activity.Order(request.Domains);

            IList <AcmeChallengeResult> challengeResults;

            // ACME Challenge を実行
            if (useDns01Auth)
            {
                // DNS-01 を使う
                challengeResults = await activity.Dns01Authorization(orderDetails.Payload.Authorizations);

                // Azure DNS で正しくレコードが引けるか確認
                await activity.CheckDnsChallenge(challengeResults);
            }
            else
            {
                // HTTP-01 を使う
                challengeResults = await activity.Http01Authorization((site, orderDetails.Payload.Authorizations));

                // HTTP で正しくアクセスできるか確認
                await activity.CheckHttpChallenge(challengeResults);
            }

            // ACME Answer を実行
            await activity.AnswerChallenges(challengeResults);

            // Order のステータスが ready になるまで 60 秒待機
            await activity.CheckIsReady(orderDetails);

            // Order の最終処理を実行し PFX を作成
            var(thumbprint, pfxBlob) = await activity.FinalizeOrder((request.Domains, orderDetails));

            await activity.UpdateCertificate((site, $"{request.Domains[0]}-{thumbprint}", pfxBlob));

            foreach (var hostNameSslState in hostNameSslStates)
            {
                hostNameSslState.Thumbprint = thumbprint;
                hostNameSslState.SslState   = request.UseIpBasedSsl ?? false ? SslState.IpBasedEnabled : SslState.SniEnabled;
                hostNameSslState.ToUpdate   = true;
            }

            await activity.UpdateSiteBinding(site);

            // クリーンアップ処理を実行
            await activity.CleanupVirtualApplication(site);
        }
        public async Task <Certificate> IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context)
        {
            var(site, dnsNames, forceDns01Challenge) = context.GetInput <(Site, string[], bool)>();

            var activity = context.CreateActivityProxy <ISharedActivity>();

            // ワイルドカード、コンテナ、Linux の場合は DNS-01 を利用する
            var useDns01Auth = forceDns01Challenge || dnsNames.Any(x => x.StartsWith("*")) || site.Kind.Contains("container") || site.Kind.Contains("linux");

            // 前提条件をチェック
            if (useDns01Auth)
            {
                await activity.Dns01Precondition(dnsNames);
            }
            else
            {
                await activity.Http01Precondition(site);
            }

            // 新しく ACME Order を作成する
            var orderDetails = await activity.Order(dnsNames);

            // 既に確認済みの場合は Challenge をスキップする
            if (orderDetails.Payload.Status != "ready")
            {
                // 複数の Authorizations を処理する
                IReadOnlyList <AcmeChallengeResult> challengeResults;

                // ACME Challenge を実行
                if (useDns01Auth)
                {
                    challengeResults = await activity.Dns01Authorization(orderDetails.Payload.Authorizations);

                    // DNS レコードの変更が伝搬するまで 10 秒遅延させる
                    await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(10), CancellationToken.None);

                    // Azure DNS で正しくレコードが引けるか確認
                    await activity.CheckDnsChallenge(challengeResults);
                }
                else
                {
                    challengeResults = await activity.Http01Authorization((site, orderDetails.Payload.Authorizations));

                    // HTTP で正しくアクセスできるか確認
                    await activity.CheckHttpChallenge(challengeResults);
                }

                // ACME Answer を実行
                await activity.AnswerChallenges(challengeResults);

                // Order のステータスが ready になるまで 60 秒待機
                await activity.CheckIsReady((orderDetails, challengeResults));

                if (useDns01Auth)
                {
                    // 作成した DNS レコードを削除
                    await activity.CleanupDnsChallenge(challengeResults);
                }
            }

            // CSR を作成し Finalize を実行
            var(finalize, rsaParameters) = await activity.FinalizeOrder((dnsNames, orderDetails));

            // Finalize の時点でステータスが valid の時点はスキップ
            if (finalize.Payload.Status != "valid")
            {
                // Finalize 後のステータスが valid になるまで 60 秒待機
                finalize = await activity.CheckIsValid(finalize);
            }

            // 証明書をダウンロードし App Service へアップロード
            var certificate = await activity.UploadCertificate((site, dnsNames[0], forceDns01Challenge, finalize, rsaParameters));
        public static async Task RunOrchestration(
            [OrchestrationTrigger] IDurableOrchestrationContext orchestrationContext,
            ILogger log)
        {
            if (orchestrationContext is null)
            {
                throw new ArgumentNullException(nameof(orchestrationContext));
            }

            if (log is null)
            {
                throw new ArgumentNullException(nameof(log));
            }

            var command       = orchestrationContext.GetInput <OrchestratorProjectComponentCreateCommand>();
            var commandResult = command.CreateResult();
            var component     = command.Payload;

            using (log.BeginCommandScope(command))
            {
                try
                {
                    orchestrationContext.SetCustomStatus("Getting provider", log);

                    var provider = await orchestrationContext
                                   .GetProviderAsync(component.ProviderId, allowUnsafe : true)
                                   .ConfigureAwait(true);

                    orchestrationContext.SetCustomStatus("Sending commands", log);

                    var providerCommand = new ProviderComponentCreateCommand
                                          (
                        command.User.PopulateExternalModel(),
                        component.PopulateExternalModel(),
                        command.ProjectId,
                        command.CommandId
                                          );

                    var providerResult = await orchestrationContext
                                         .SendProviderCommandAsync <ProviderComponentCreateCommand, ProviderComponentCreateCommandResult>(providerCommand, provider)
                                         .ConfigureAwait(true);

                    providerResult.Errors.ToList().ForEach(e => commandResult.Errors.Add(e));

                    commandResult.Result = component.PopulateFromExternalModel(providerResult.Result);

                    orchestrationContext.SetCustomStatus($"Component created.", log);
                }
                catch (Exception exc)
                {
                    commandResult ??= command.CreateResult();
                    commandResult.Errors.Add(exc);
                }
                finally
                {
                    var commandException = commandResult.Errors?.ToException();

                    if (commandException is null)
                    {
                        orchestrationContext.SetCustomStatus($"Command succeeded", log);
                    }
                    else
                    {
                        orchestrationContext.SetCustomStatus($"Command failed", log, commandException);
                    }

                    orchestrationContext.SetOutput(commandResult);
                }
            }
        }
        public static async Task <object> ProcessNumbers([OrchestrationTrigger]
                                                         IDurableOrchestrationContext ctx, ILogger log)
        {
            string[] numbers                = null;
            string   callinfoAfterCall      = null;
            string   answeredCallTaskResult = null;
            bool     callAnswered           = false;

            try
            {
                // ***************************** STEP 1 - get the phone numbers from storage* *****************************************

                if (!ctx.IsReplaying)
                {
                    log.LogWarning("About to call A_GetNumbersFromStorage activity");
                }

                // Get the number from storage
                numbers = await ctx.CallActivityAsync <string[]>("A_GetNumbersFromStorage", null);

                CallInfo callinfo = new CallInfo
                {
                    InstanceId = ctx.InstanceId,
                    Numbers    = numbers
                };

                // ***************************** STEP 2 - Attempt to make a call ******************************************
                if (!ctx.IsReplaying)
                {
                    log.LogWarning("About to call A_MakeCall activity");
                }


                // Attempt to call the numbers retrieved from storage
                ////foreach (var number in numbers)
                ////{
                ////    var done = false;
                ////    done = await ctx.CallNumberAsync(number, log);

                ////    if (done)
                ////    {
                ////        break;
                ////    }
                ////}

                callinfoAfterCall = await ctx.CallActivityAsync <string>("A_MakeCall", callinfo);

                using (var cts = new CancellationTokenSource())
                {
                    var timeout          = ctx.CurrentUtcDateTime.AddSeconds(60);
                    var timeoutTask      = ctx.CreateTimer(timeout, cts.Token);
                    var answeredCallTask = ctx.WaitForExternalEvent <string>("AnsweredCallResult", TimeSpan.FromSeconds(60), cts.Token);

                    var winner = await Task.WhenAny(answeredCallTask, timeoutTask);

                    if (winner == answeredCallTask)
                    {
                        log.LogWarning($"Call answered at {ctx.CurrentUtcDateTime}");
                        callAnswered = true;

                        answeredCallTaskResult = answeredCallTask.Result;
                        cts.Cancel();
                    }
                    else
                    {
                        callAnswered           = false;
                        answeredCallTaskResult = "Timed Out";
                    }
                }

                return(new
                {
                    CallAnswered = callAnswered,
                    Success = true,
                    OrchestrationId = ctx.InstanceId
                });
            }
            catch (Exception e)
            {
                // Log Exception, pefrom any cleanup
                return(new
                {
                    Success = false,
                    Error = e.Message
                });
            }
        }
예제 #24
0
        public static async Task ShareAllTickets([OrchestrationTrigger] IDurableOrchestrationContext context)
        {
            var tickets = await context.CallActivityAsync <long[]>(nameof(DurableWatcher.SearchTickets), null);

            await ShareTickets(context, tickets);
        }
        public async Task RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            [DurableClient] IDurableOrchestrationClient processStarter,
            ILogger log)
        {
            _correlationInitializer.Initialize(context.InstanceId);

            var beginProcessCommand = this.BuildBeginProcessCommand(context);
            await context.CallActivityAsync <Task>(nameof(StatusTracker), beginProcessCommand);

            var command = context.GetInput <RegisterApplicationCommand>();

            var uploadCvCommand = new UploadCvCommand(
                command.Cv.File,
                command.Cv.ContentType,
                command.Cv.Extension);

            var uploadPhotoCommand = new UploadPhotoCommand(
                command.Photo.File,
                command.Photo.ContentType,
                command.Photo.Extension);

            await Task.WhenAll(
                context.CallActivityAsync <Task>(nameof(CvUploader), uploadCvCommand),
                context.CallActivityAsync <Task>(nameof(PhotoUploader), uploadPhotoCommand));

            var cvUploadedEventTask     = context.WaitForExternalEvent <CvUploadedInternalFunctionEvent>(nameof(CvUploadedInternalFunctionEvent));
            var cvUploadFailedEventTask = context.WaitForExternalEvent <CvUploadFailedInternalFunctionEvent>(nameof(CvUploadFailedInternalFunctionEvent));

            var photoUploadedEventTask     = context.WaitForExternalEvent <PhotoUploadedInternalFunctionEvent>(nameof(PhotoUploadedInternalFunctionEvent));
            var photoUploadFailedEventTask = context.WaitForExternalEvent <PhotoUploadFailedInternalFunctionEvent>(nameof(PhotoUploadFailedInternalFunctionEvent));

            var cvUploadEventTask = await Task.WhenAny(cvUploadedEventTask, cvUploadFailedEventTask);

            var photoUploadEventTask = await Task.WhenAny(photoUploadedEventTask, photoUploadFailedEventTask);

            var cvUploadedSuccessfully    = cvUploadEventTask == cvUploadedEventTask;
            var photoUploadedSuccessfully = photoUploadEventTask == photoUploadedEventTask;

            if (!cvUploadedSuccessfully || !photoUploadedSuccessfully)
            {
                await this.HandleUploadFilesFailure(
                    context,
                    processStarter,
                    log,
                    photoUploadFailedEventTask,
                    cvUploadFailedEventTask,
                    command);

                return;
            }

            log.LogProgress(OperationStatus.InProgress, "Finished the files uploading", context.InstanceId);
            var cvUri    = cvUploadedEventTask.Result.CvUri;
            var photoUri = photoUploadedEventTask.Result.PhotoUri;

            var saveApplicationCommand = new CreateApplicationCommand(
                context.InstanceId,
                command.Candidate.FirstName,
                command.Candidate.LastName,
                photoUri,
                cvUri,
                command.Candidate.Category,
                command.CreationTime,
                command.Candidate.EducationLevel,
                command.Candidate.Address,
                command.Candidate.FinishedSchools,
                command.Candidate.ConfirmedSkills,
                command.Candidate.WorkExperiences,
                context.InstanceId);

            await context.CallActivityAsync <Task>(nameof(ApplicationSaver), saveApplicationCommand);

            var applicationSavedEvent = context.WaitForExternalEvent <ApplicationSavedInternalFunctionEvent>(nameof(ApplicationSavedInternalFunctionEvent));
            var applicationSaveFailed = context.WaitForExternalEvent <ApplicationSaveFailedInternalFunctionEvent>(nameof(ApplicationSaveFailedInternalFunctionEvent));
            var applicationSaveEvent  = await Task.WhenAny(applicationSavedEvent, applicationSaveFailed);

            var applicationSavedSuccessfully = applicationSaveEvent == applicationSavedEvent;

            if (!applicationSavedSuccessfully)
            {
                log.LogFailedOperation(OperationStatus.Failed, "Storing application failed", applicationSaveFailed.Result.Errors, context.InstanceId);
                var failedProcessCommand = this.BuildFailedProcessCommand(context, applicationSaveFailed.Result.Errors);
                await context.CallActivityAsync <Task>(nameof(StatusTracker), failedProcessCommand);

                await this.StartRecompensateProcess(processStarter, context, command, log);

                return;
            }

            var finishProcessCommand = this.BuildFinishedProcessCommand(context);
            await context.CallActivityAsync <Task>(nameof(StatusTracker), finishProcessCommand);
        }
예제 #26
0
        public static async Task ShareListedTickets([OrchestrationTrigger] IDurableOrchestrationContext context)
        {
            var tickets = context.GetInput <long[]>();

            await ShareTickets(context, tickets);
        }
예제 #27
0
        public static async Task RunOrchestration(
            [OrchestrationTrigger] IDurableOrchestrationContext functionContext,
            ILogger log)
        {
            if (functionContext is null)
            {
                throw new ArgumentNullException(nameof(functionContext));
            }

            if (log is null)
            {
                throw new ArgumentNullException(nameof(log));
            }

            var command       = functionContext.GetInput <OrchestratorTeamCloudUserDeleteCommand>();
            var commandResult = command.CreateResult();
            var user          = command.Payload;

            using (log.BeginCommandScope(command))
            {
                try
                {
                    functionContext.SetCustomStatus($"Deleting user.", log);

                    using (await functionContext.LockAsync <UserDocument>(user.Id.ToString()).ConfigureAwait(true))
                    {
                        await functionContext
                        .DeleteUserAsync(user.Id)
                        .ConfigureAwait(true);
                    }

                    var projects = default(IEnumerable <ProjectDocument>);

                    // TODO: this is totally wrong
                    // only update all projects if user was an admin
                    if (user.IsAdmin())
                    {
                        projects = await functionContext
                                   .ListProjectsAsync()
                                   .ConfigureAwait(true);
                    }
                    else if (user.ProjectMemberships.Any())
                    {
                        projects = await functionContext
                                   .ListProjectsAsync(user.ProjectMemberships.Select(m => m.ProjectId).ToList())
                                   .ConfigureAwait(true);
                    }

                    if (projects?.Any() ?? false)
                    {
                        foreach (var project in projects)
                        {
                            var projectUpdateCommand = new OrchestratorProjectUpdateCommand(command.BaseApi, command.User, project);

                            functionContext.StartNewOrchestration(nameof(OrchestratorProjectUpdateCommandOrchestration), projectUpdateCommand);
                        }
                    }

                    commandResult.Result = user;

                    functionContext.SetCustomStatus($"User deleted.", log);
                }
                catch (Exception ex)
                {
                    functionContext.SetCustomStatus("Failed to delete user.", log, ex);

                    commandResult ??= command.CreateResult();
                    commandResult.Errors.Add(ex);

                    throw;
                }
                finally
                {
                    functionContext.SetOutput(commandResult);
                }
            }
        }
예제 #28
0
 public static Task SetInstrumentationKeyAsync(this IDurableOrchestrationContext functionContext, Guid instrumentationKey)
 => instrumentationKey.ToString().Equals(Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY"), StringComparison.OrdinalIgnoreCase)
     ? Task.CompletedTask : functionContext.SetAppSettingAsync("APPINSIGHTS_INSTRUMENTATIONKEY", instrumentationKey.ToString());
예제 #29
0
 public AzureGenerator(FractalOptions options, IDurableOrchestrationContext context, int chunks = 8) : base(options)
 {
     _context = context;
     _chunks  = chunks;
 }
예제 #30
0
        public static async Task <object> ProcessVideo(
            [OrchestrationTrigger] IDurableOrchestrationContext ctx,
            ILogger log)
        {
            var    cart           = ctx.GetInput <CartDto>();
            string paid           = null;
            string shipped        = null;
            string inventoryDone  = null;
            string approvalResult = "Unknown";
            string token          = null;

            try
            {
                /*
                 * if (!ctx.IsReplaying)
                 *  log.LogInformation("About to call an purchased activity");
                 *
                 * paid = await ctx.CallActivityAsync<string>("A_Payment", cart);
                 *
                 * if (!ctx.IsReplaying)
                 *  log.LogInformation("About to call shipping");
                 *
                 * shipped = await ctx.CallActivityAsync<string>("A_Shipping", cart);
                 *
                 * if (!ctx.IsReplaying)
                 *  log.LogInformation("About to call inventory");
                 *
                 * inventoryDone = await ctx.CallActivityAsync<string>("A_Inventory", cart);
                 */



                await ctx.CallActivityAsync("A_SendApprovalRequestEmail", new ApprovalInfo()
                {
                    OrchestrationId = ctx.InstanceId,
                    Message         = "activate your account."
                });

                using (var cts = new CancellationTokenSource())
                {
                    var timeoutAt    = ctx.CurrentUtcDateTime.AddMinutes(5);
                    var timeoutTask  = ctx.CreateTimer(timeoutAt, cts.Token);
                    var approvalTask = ctx.WaitForExternalEvent <string>("ApprovalResult");

                    var winner = await Task.WhenAny(approvalTask, timeoutTask);

                    if (winner == approvalTask)
                    {
                        approvalResult = approvalTask.Result;
                        cts.Cancel(); // we should cancel the timeout task
                    }
                    else
                    {
                        approvalResult = "Timed Out";
                    }
                }

                if (approvalResult == "Approved")
                {
                    token = await ctx.CallActivityAsync <string>("A_GetGigyaToken", cart.Name);//Name is the email.
                }
                else
                {
                    await ctx.CallActivityAsync("A_Reject", "rejected");
                }
            }
            catch (Exception e)
            {
                if (!ctx.IsReplaying)
                {
                    log.LogError($"Caught an error from an activity: {e.Message}");
                }

                await
                ctx.CallActivityAsync <string>("A_Cleanup",
                                               new[] { paid ?? "", shipped ?? "", inventoryDone ?? "" });

                return(new
                {
                    Error = "Failed to process the purchase",
                    Message = e.Message,
                    Paid = paid ?? "",
                    Shipped = shipped ?? "",
                    InventoryDone = inventoryDone ?? ""
                });
            }

            return(new CheckoutReturnDto
            {
                Paid = paid,
                Shipped = shipped,
                InventoryDone = inventoryDone,
                Token = token
            });
        }