public static async Task <ActivityResponse <Command_Notification_Response> > GetCommandNotificationsActivity([ActivityTrigger] DurableActivityContext context,
                                                                                                                     ILogger log)
        {
            ActivityResponse <Command_Notification_Response> response = new ActivityResponse <Command_Notification_Response>()
            {
                FunctionName = "CommandNotificationActivity",
                ReturnedData = new Command_Notification_Response()
            };

            Command_Get_Notifications_Request payload = context.GetInput <Command_Get_Notifications_Request>();

            if (null != payload)
            {
                // run the projection to send the notifications..
                Projection getCommandNotifications = new Projection(Constants.Domain_Command,
                                                                    payload.CommandName,
                                                                    payload.CommandUniqueIdentifier,
                                                                    nameof(Command_Notifications_Projection));

                Command_Notifications_Projection cmdProjection = new Command_Notifications_Projection(log);

                await getCommandNotifications.Process(cmdProjection);

                if ((cmdProjection.CurrentSequenceNumber > 0) || (cmdProjection.ProjectionValuesChanged()))
                {
                    // Send the completed notification if the command is complete
                    if (cmdProjection.Completed)
                    {
                        // make it an "all completed" notification
                        response.ReturnedData.Completed = true;
                    }
                    else if (cmdProjection.InError)
                    {
                        // make it an "all completed" notification
                        response.ReturnedData.InError = true;
                    }
                    else
                    {
                        // otherwise send each step notification
                        foreach (CommandStepCompleted stepCompleted in cmdProjection.StepsCompleted)
                        {
                            // make it a "steps completed" notification
                        }
                    }

                    if (null != cmdProjection.ImpactedEntities)
                    {
                        response.ReturnedData.ImpactedEntities = cmdProjection.ImpactedEntities;
                    }

                    if (null != cmdProjection.NotificationTargetHooks)
                    {
                        response.ReturnedData.NotificationTargetHooks = cmdProjection.NotificationTargetHooks;
                    }
                }
            }

            return(response);
        }
        public static async Task <HttpResponseMessage> CommandNotificationRun(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequestMessage req,
            [OrchestrationClient] DurableOrchestrationClient runNotificationOrchestrationClient,
            ILogger log)
        {
            #region Logging
            if (null != log)
            {
                log.LogInformation("Sending command notifications for a command");
            }
            #endregion

            int timeoutLength = 30; // seconds
            int retryWait     = 1;  // seconds

            string commandId   = req.RequestUri.ParseQueryString()["CommandId"];
            string commandName = req.RequestUri.ParseQueryString()["CommandName"];

            // Get a timeout and retry wait if they are passed in as parameters
            string timeoutLengthString = req.RequestUri.ParseQueryString()["TimeOut"];
            if (!string.IsNullOrWhiteSpace(timeoutLengthString))
            {
                int.TryParse(timeoutLengthString, out timeoutLength);
            }
            string retryWaitString = req.RequestUri.ParseQueryString()["RetryWait"];
            if (!string.IsNullOrWhiteSpace(retryWaitString))
            {
                int.TryParse(retryWaitString, out retryWait);
            }

            // Check if the parameters have been passed in the http request body
            dynamic eventData = await req.Content.ReadAsAsync <object>();

            if (null != eventData)
            {
                commandId   = commandId ?? eventData?.CommandId;
                commandName = commandName ?? eventData?.CommandName;
            }

            // Fire the orchestration to do the actual work of sending notifications
            Command_Get_Notifications_Request payload = new Command_Get_Notifications_Request()
            {
                CommandName             = commandName,
                CommandUniqueIdentifier = commandId
            };

            // call the orchestrator...
            string instanceId = await runNotificationOrchestrationClient.StartNewAsync("CommandNotificationOrchestrator", payload);


            #region Logging
            if (null != log)
            {
                log.LogInformation($"Started CommandNotificationOrchestrator - instance id: {instanceId }");
            }
            #endregion

            // Wait for it to complete
            TimeSpan timeout       = TimeSpan.FromSeconds(timeoutLength);
            TimeSpan retryInterval = TimeSpan.FromSeconds(retryWait);

            return(await runNotificationOrchestrationClient.WaitForCompletionOrCreateCheckStatusResponseAsync(
                       req,
                       instanceId,
                       timeout,
                       retryInterval));
        }
        public static async Task <ActivityResponse> CommandNotificationOrchestrator(
            [OrchestrationTrigger] DurableOrchestrationContext context,
            Microsoft.Extensions.Logging.ILogger log)
        {
            ActivityResponse <Command_Notification_Response> response = new ActivityResponse <Command_Notification_Response>()
            {
                FunctionName = "CommandNotificationOrchestrator"
            };

            Command_Get_Notifications_Request request = context.GetInput <Command_Get_Notifications_Request>();

            if (null != request)
            {
                Guid UniqueIdentifierGuid;
                if (Guid.TryParse(request.CommandUniqueIdentifier, out UniqueIdentifierGuid))
                {
                    // run the [Command_Notifications_Projection]..
                    response = await context.CallActivityAsync <ActivityResponse <Command_Notification_Response> >("GetCommandNotificationsActivity", request);

                    if (null != response)
                    {
                        if ((!response.FatalError) && (!response.StepFailure))
                        {
                            if (null != response.ReturnedData)
                            {
                                List <Task <ActivityResponse> > allNotificationTasks = new List <Task <ActivityResponse> >();

                                // Only process the notifications that match the state of the command...
                                IEnumerable <ReturnHookAdded> notificationHooks = null;
                                if (response.ReturnedData.InError)
                                {
                                    notificationHooks = response.ReturnedData.NotificationTargetHooks.ForErrors();
                                }
                                else
                                {
                                    if (response.ReturnedData.Completed)
                                    {
                                        notificationHooks = response.ReturnedData.NotificationTargetHooks.ForCompleteCommands();
                                    }
                                    else
                                    {
                                        notificationHooks = response.ReturnedData.NotificationTargetHooks.ForStepComplete();
                                    }
                                }

                                // fire off all the notifications in parrallel
                                foreach (var notificationTarget in notificationHooks)
                                {
                                    foreach (var notifyEntity in response.ReturnedData.ImpactedEntities)
                                    {
                                        // create an individual notification request
                                        Command_Notification_Request notifyRequest = new Command_Notification_Request()
                                        {
                                            CommandName             = request.CommandName,
                                            CommandNotificationType = Command_Notification_Request.NotificationType.StepComplete,
                                            HookAddress             = notificationTarget.HookAddress,
                                            HookType       = notificationTarget.HookType,
                                            ImpactedEntity = notifyEntity
                                        };

                                        if (response.ReturnedData.InError)
                                        {
                                            notifyRequest.CommandNotificationType = Command_Notification_Request.NotificationType.Error;
                                        }
                                        else
                                        {
                                            if (response.ReturnedData.Completed)
                                            {
                                                notifyRequest.CommandNotificationType = Command_Notification_Request.NotificationType.CommandComplete;
                                            }
                                        }

                                        if (notificationTarget.HookType == CommandNotificationTarget.NotificationTargetType.CustomEventGridTopic)
                                        {
                                            // RunCustomEventGridTopicNotificationActivity
                                            allNotificationTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("RunCustomEventGridTopicNotificationActivity",
                                                                                                                           DomainSettings.CommandRetryOptions(),
                                                                                                                           notifyRequest));
                                        }

                                        if (notificationTarget.HookType == CommandNotificationTarget.NotificationTargetType.WebHook)
                                        {
                                            // RunWebHookNotificationActivity
                                            allNotificationTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("RunWebHookNotificationActivity",
                                                                                                                           DomainSettings.CommandRetryOptions(),
                                                                                                                           notifyRequest));
                                        }

                                        if (notificationTarget.HookType == CommandNotificationTarget.NotificationTargetType.SignalR)
                                        {
                                            //RunSignalRNotificationActivity
                                            allNotificationTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("RunSignalRNotificationActivity",
                                                                                                                           DomainSettings.CommandRetryOptions(),
                                                                                                                           notifyRequest));
                                        }
                                    }
                                }

                                // Run the projections in parallel...
                                await Task.WhenAll(allNotificationTasks);
                            }
                        }
                        else
                        {
                            #region Logging
                            if (null != log)
                            {
                                log.LogError($"{response.FunctionName} error - no data returned - {response.Message} ");
                            }
                            #endregion
                        }
                    }
                }
                else
                {
                    response.FatalError = true;
                    response.Message    = $"Unable to get command unique identifier for {request.CommandName} {request.CommandUniqueIdentifier } as a GUID ";
                }
            }

            return(response);
        }