public static async Task <List <Query_Projections_Projection_Return> > GetQueryProjectionsStatusProjectionActivity(
            [ActivityTrigger] DurableActivityContext context,
            ILogger log
            )
        {
            Query_Projections_Projection_Request queryInfo = context.GetInput <Query_Projections_Projection_Request>();

            #region Logging
            if (null != log)
            {
                log.LogInformation($"GetQueryProjectionsStatusProjectionActivity called for query ID: {queryInfo.UniqueIdentifier }");
            }
            #endregion

            return(await ProcessQueryProjectionsStatusProjection(
                       queryInfo.QueryName,
                       queryInfo.UniqueIdentifier,
                       log));
        }
        public static async Task <Get_League_Summary_Definition_Return> OnGetLeagueSummaryQueryHandlerOrchestrator
            ([OrchestrationTrigger] DurableOrchestrationContext context,
            Microsoft.Extensions.Logging.ILogger log)
        {
            // Get the query definition form the context...
            QueryRequest <Get_League_Summary_Definition> queryRequest = context.GetInput <QueryRequest <Get_League_Summary_Definition> >();



            try
            {
                if (null != queryRequest)
                {
                    if (string.IsNullOrWhiteSpace(queryRequest.QueryName))
                    {
                        queryRequest.QueryName = "Get League Summary";
                    }

                    // Log the query request in its own own query event stream
                    Guid queryId = await context.CallActivityWithRetryAsync <Guid>("GetLeagueSummaryCreateQueryRequestActivity",
                                                                                   DomainSettings.QueryRetryOptions(),
                                                                                   queryRequest);

                    if (queryId.Equals(Guid.Empty))
                    {
                        #region Logging
                        if (null != log)
                        {
                            // Unable to get the request details from the orchestration
                            log.LogError("OnGetLeagueSummaryQueryHandlerOrchestrator : Unable to create the query event stream");
                        }
                        #endregion

                        return(null);
                    }
                    else
                    {
                        queryRequest.QueryUniqueIdentifier = queryId;
                        // Save the parameters to the event stream
                        ActivityResponse resp = null;

                        resp = await context.CallActivityWithRetryAsync <ActivityResponse>("GetLeagueSummaryLogParametersActivity",
                                                                                           DomainSettings.QueryRetryOptions(),
                                                                                           queryRequest);

                        #region Logging
                        if (null != log)
                        {
                            if (null != resp)
                            {
                                log.LogInformation($"{resp.FunctionName} complete: {resp.Message } ");
                            }
                        }
                        #endregion


                        if (null != resp)
                        {
                            context.SetCustomStatus(resp);
                        }

                        // next validate the query
                        bool valid = false;

                        try
                        {
                            valid = await context.CallActivityWithRetryAsync <bool>("GetLeagueSummaryValidateActivity",
                                                                                    DomainSettings.QueryRetryOptions(),
                                                                                    queryRequest);
                        }
                        catch (FunctionFailedException ffs)
                        {
                            if (null == resp)
                            {
                                resp = new ActivityResponse()
                                {
                                    FunctionName = "QueryProjectionProcessorOrchestrator"
                                };
                            }
                            resp.Message    = ffs.Message;
                            resp.FatalError = true;
                        }

                        if (!valid)
                        {
                            #region Logging
                            if (null != log)
                            {
                                // Could not run the query as the parameters don't make sense
                                log.LogError($"OnGetLeagueSummaryQueryHandlerOrchestrator : Query parameters are invalid {queryId}");
                            }
                            #endregion
                            return(null);
                        }
                        else
                        {
                            try
                            {
                                // Request all the projections needed to answer this query
                                resp = await context.CallActivityWithRetryAsync <ActivityResponse>("GetLeagueSummaryQueryProjectionRequestActivity",
                                                                                                   DomainSettings.QueryRetryOptions(),
                                                                                                   queryRequest);
                            }
                            catch (FunctionFailedException ffs)
                            {
                                if (null == resp)
                                {
                                    resp = new ActivityResponse()
                                    {
                                        FunctionName = "QueryProjectionProcessorOrchestrator"
                                    };
                                }
                                resp.Message    = ffs.Message;
                                resp.FatalError = true;
                            }

                            if (null != resp)
                            {
                                #region Logging
                                if (null != log)
                                {
                                    if (null != resp)
                                    {
                                        log.LogInformation($"{resp.FunctionName} complete: {resp.Message } ");
                                    }
                                }
                                #endregion
                                context.SetCustomStatus(resp);
                                if (resp.FatalError)
                                {
                                    #region Logging
                                    if (null != log)
                                    {
                                        log.LogError($"Fatal error in {resp.FunctionName} - {resp.Message} ");
                                    }
                                    #endregion
                                    return(null);
                                }
                            }

                            // Get all the outstanding projection requests by calling a sub-orchestrator
                            Query_Projections_Projection_Request projectionQueryRequest = new Query_Projections_Projection_Request()
                            {
                                UniqueIdentifier = queryRequest.QueryUniqueIdentifier.ToString(), QueryName = queryRequest.QueryName
                            };

                            try
                            {
                                resp = await context.CallSubOrchestratorWithRetryAsync <ActivityResponse>("QueryProjectionProcessorOrchestrator",
                                                                                                          DomainSettings.QueryRetryOptions(),
                                                                                                          projectionQueryRequest);
                            }
                            catch (FunctionFailedException ffs)
                            {
                                if (null == resp)
                                {
                                    resp = new ActivityResponse()
                                    {
                                        FunctionName = "QueryProjectionProcessorOrchestrator"
                                    };
                                }
                                resp.Message    = ffs.Message;
                                resp.FatalError = true;
                            }

                            if (null != resp)
                            {
                                #region Logging
                                if (null != log)
                                {
                                    if (null != resp)
                                    {
                                        log.LogInformation($"{resp.FunctionName} complete: {resp.Message } ");
                                    }
                                }
                                #endregion
                                context.SetCustomStatus(resp);
                                if (resp.FatalError)
                                {
                                    #region Logging
                                    if (null != log)
                                    {
                                        log.LogError($"Fatal error in {resp.FunctionName} - {resp.Message} ");
                                    }
                                    #endregion
                                    return(null);
                                }
                            }

                            try
                            {
                                // Output the results
                                resp = await context.CallActivityWithRetryAsync <ActivityResponse>("GetLeagueSummaryOutputResultsActivity",
                                                                                                   DomainSettings.QueryRetryOptions(),
                                                                                                   queryRequest);
                            }
                            catch (FunctionFailedException ffs)
                            {
                                if (null == resp)
                                {
                                    resp = new ActivityResponse()
                                    {
                                        FunctionName = "QueryProjectionProcessorOrchestrator"
                                    };
                                }
                                resp.Message    = ffs.Message;
                                resp.FatalError = true;
                            }

                            #region Logging
                            if (null != log)
                            {
                                if (null != resp)
                                {
                                    log.LogInformation($"{resp.FunctionName} complete: {resp.Message } ");
                                }
                            }
                            #endregion
                            if (null != resp)
                            {
                                context.SetCustomStatus(resp);
                                if (resp.FatalError)
                                {
                                    #region Logging
                                    if (null != log)
                                    {
                                        log.LogError($"Fatal error in {resp.FunctionName} - {resp.Message} ");
                                    }
                                    #endregion
                                    return(null);
                                }
                            }

                            // Get the results for ourselves to return...to do this the query must be complete...
                            Get_League_Summary_Definition_Return ret = await context.CallActivityWithRetryAsync <Get_League_Summary_Definition_Return>("GetLeagueSummaryGetResultsActivity",
                                                                                                                                                       DomainSettings.QueryRetryOptions(),
                                                                                                                                                       queryRequest);

                            return(ret);
                        }
                    }
                }
                else
                {
                    if (null != log)
                    {
                        // Unable to get the request details from the orchestration
                        log.LogError("OnGetLeagueSummaryQueryHandlerOrchestrator : Unable to get the query request from the context");

                        string contextAsString = context.GetInput <string>();
                        if (!string.IsNullOrWhiteSpace(contextAsString))
                        {
                            log.LogError($"Context was {contextAsString} ");
                        }
                        else
                        {
                            log.LogError($"Context was blank ");
                        }
                    }

                    return(null);
                }
            }
            catch (Exception ex)
            {
                #region Logging
                if (null != log)
                {
                    // Error running thew orchestration
                    log.LogError($"OnGetLeagueSummaryQueryHandlerOrchestrator : Error {ex.Message}");
                }
                #endregion
                if (null != context)
                {
                    context.SetCustomStatus($"OnGetLeagueSummaryQueryHandlerOrchestrator : Error {ex.Message}");
                }
                throw;
            }
        }
Example #3
0
        public static async Task <HttpResponseMessage> QueryProjectionProcessorRun(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequestMessage req,
            [OrchestrationClient] DurableOrchestrationClient runProjectionOrchestrationClient,
            ILogger log)
        {
            #region Logging
            if (null != log)
            {
                log.LogInformation("Get all query status by name");
            }
            #endregion

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

            string   queryId             = req.RequestUri.ParseQueryString()["QueryId"];
            string   queryName           = req.RequestUri.ParseQueryString()["QueryName"];
            string   notifyOrchestration = req.RequestUri.ParseQueryString()["NotifyOrchestration"];
            string   asOfDateString      = req.RequestUri.ParseQueryString()["AsOfDate"];
            DateTime?asOfDate            = null;
            if (!string.IsNullOrWhiteSpace(asOfDateString))
            {
                DateTime dtOut;
                if (DateTime.TryParse(asOfDateString, out dtOut))
                {
                    asOfDate = dtOut;
                }
            }
            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);
            }

            dynamic eventData = await req.Content.ReadAsAsync <object>();

            if (null != eventData)
            {
                queryId             = queryId ?? eventData?.QueryId;
                queryName           = queryName ?? eventData?.QueryName;
                asOfDate            = asOfDate ?? eventData?.AsOfDate;
                notifyOrchestration = notifyOrchestration ?? eventData?.NotifyOrchestration;
            }

            if (!string.IsNullOrWhiteSpace(queryId))
            {
                Query_Projections_Projection_Request payload = new Query_Projections_Projection_Request()
                {
                    QueryName        = queryName,
                    UniqueIdentifier = queryId,
                    AsOfDate         = asOfDate,
                    CallbackOrchestrationIdentifier = notifyOrchestration
                };

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


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

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

                return(await runProjectionOrchestrationClient.WaitForCompletionOrCreateCheckStatusResponseAsync(
                           req,
                           instanceId,
                           timeout,
                           retryInterval));
            }
            else
            {
                return(req.CreateResponse(System.Net.HttpStatusCode.BadRequest, "Please pass a query name and query identifier in the query string or in the request body"));
            }
        }
Example #4
0
        public static async Task <ActivityResponse> QueryProjectionProcessorOrchestrator(
            [OrchestrationTrigger] DurableOrchestrationContext context,
            Microsoft.Extensions.Logging.ILogger log)
        {
            ActivityResponse response = new ActivityResponse()
            {
                FunctionName = "QueryProjectionProcessorOrchestrator"
            };

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

            if (null != request)
            {
                Guid UniqueIdentifierGuid;
                if (!Guid.TryParse(request.UniqueIdentifier, out UniqueIdentifierGuid))
                {
                    if (!Guid.TryParse(request.CallbackOrchestrationIdentifier, out UniqueIdentifierGuid))
                    {
                        if (!Guid.TryParse(context.ParentInstanceId, out UniqueIdentifierGuid))
                        {
                            if (!Guid.TryParse(context.InstanceId, out UniqueIdentifierGuid))
                            {
                                UniqueIdentifierGuid = Guid.NewGuid();
                            }
                        }
                    }
                }



                // get all the projection requests for the query
                List <Query_Projections_Projection_Return> allProjections = await context.CallActivityWithRetryAsync <List <Query_Projections_Projection_Return> >("GetQueryProjectionsStatusProjectionActivity",
                                                                                                                                                                   DomainSettings.QueryRetryOptions(),
                                                                                                                                                                   request);

                if (null != allProjections)
                {
                    #region Logging
                    if (null != log)
                    {
                        log.LogInformation($"Query {request.QueryName}.{request.UniqueIdentifier} has {allProjections.Count} projections total ");
                    }
                    #endregion

                    // Run them - This should be done by fan-out/fan-in
                    List <Task <ProjectionResultsRecord <object> > > allProjectionTasks = new List <Task <ProjectionResultsRecord <object> > >();

                    // run all the outstanding projections in parallel
                    foreach (Query_Projections_Projection_Return projectionRequest in allProjections)
                    {
                        if (projectionRequest.ProjectionState == Query_Projections_Projection_Return.QueryProjectionState.Queued)
                        {
                            ProjectionRequest projRequest = new ProjectionRequest()
                            {
                                ParentRequestName                 = request.QueryName,
                                CorrelationIdentifier             = UniqueIdentifierGuid,
                                DomainName                        = projectionRequest.Projection.DomainName,
                                AggregateTypeName                 = projectionRequest.Projection.AggregateTypeName,
                                AggregateInstanceUniqueIdentifier = projectionRequest.Projection.InstanceKey,
                                AsOfDate       = request.AsOfDate,
                                ProjectionName = projectionRequest.Projection.ProjectionTypeName
                            };

                            if (null != projRequest)
                            {
                                context.SetCustomStatus(projRequest);
                            }


                            // mark it as in-flight
                            response = await context.CallActivityWithRetryAsync <ActivityResponse>("LogQueryProjectionInFlightActivity",
                                                                                                   DomainSettings.QueryRetryOptions(),
                                                                                                   projRequest);

                            if (null != response)
                            {
                                context.SetCustomStatus(response);
                            }
                        }
                    }

                    // Now start them running using a fan-out/fan in pattern
                    foreach (Query_Projections_Projection_Return projectionRequest in allProjections)
                    {
                        if (projectionRequest.ProjectionState == Query_Projections_Projection_Return.QueryProjectionState.Queued)
                        {
                            ProjectionRequest projRequest = new ProjectionRequest()
                            {
                                ParentRequestName                 = request.QueryName,
                                CorrelationIdentifier             = UniqueIdentifierGuid,
                                DomainName                        = projectionRequest.Projection.DomainName,
                                AggregateTypeName                 = projectionRequest.Projection.AggregateTypeName,
                                AggregateInstanceUniqueIdentifier = projectionRequest.Projection.InstanceKey,
                                AsOfDate       = request.AsOfDate,
                                ProjectionName = projectionRequest.Projection.ProjectionTypeName
                            };


                            // and start running it...
                            allProjectionTasks.Add(context.CallActivityWithRetryAsync <ProjectionResultsRecord <object> >("RunProjectionActivity",
                                                                                                                          DomainSettings.QueryRetryOptions(),
                                                                                                                          projRequest));
                        }
                    }

                    // Run the projections in parallel...
                    await Task.WhenAll(allProjectionTasks);

                    // and save their results to the query
                    foreach (var returnValue in allProjectionTasks)
                    {
                        ProjectionResultsRecord <object> result = returnValue.Result;

                        if (null != result)
                        {
                            if (!result.Error)
                            {
                                response = await context.CallActivityWithRetryAsync <ActivityResponse>("LogQueryProjectionResultActivity",
                                                                                                       DomainSettings.QueryRetryOptions(),
                                                                                                       result);
                            }
                            else
                            {
                                #region Logging
                                if (null != log)
                                {
                                    log.LogError($"Error running projection {result.ProjectionName} - {result.StatusMessage} ");
                                }
                                #endregion
                                response.Message = $"Error running projection {result.ProjectionName} - {result.StatusMessage} ";
                            }
                            if (null != response)
                            {
                                context.SetCustomStatus(response);
                            }
                        }
                        else
                        {
                            #region Logging
                            if (null != log)
                            {
                                log.LogError($"Projection {returnValue.Id} did not return any values : {returnValue.Exception}");
                            }
                            #endregion
                        }
                    }
                }


                // when all done - trigger the calling orchestration to come out of hibernation
                if (!string.IsNullOrWhiteSpace(request.CallbackOrchestrationIdentifier))
                {
                }
            }
            else
            {
                response.Message    = $"Unable to read projection request data from context {context.InstanceId}";
                response.FatalError = true;
            }

            return(response);
        }
Example #5
0
        public static async Task <ActivityResponse> GetLeagueSummaryQueryProjectionProcessOrchestrator
            ([OrchestrationTrigger] DurableOrchestrationContext context,
            Microsoft.Extensions.Logging.ILogger log)
        {
            ActivityResponse resp = new ActivityResponse()
            {
                FunctionName = "GetLeagueSummaryQueryProjectionProcessOrchestrator"
            };

            // Get the query definition form the context...
            QueryRequest <Get_League_Summary_Definition> queryRequest = context.GetInput <QueryRequest <Get_League_Summary_Definition> >();

            if (null != queryRequest)
            {
                // Get all the outstanding projection requests
                Query_Projections_Projection_Request projectionQueryRequest = new Query_Projections_Projection_Request()
                {
                    UniqueIdentifier = queryRequest.QueryUniqueIdentifier.ToString(),
                    QueryName        = queryRequest.QueryName
                };
                List <Query_Projections_Projection_Return> allProjections = await context.CallActivityAsync <List <Query_Projections_Projection_Return> >("GetQueryProjectionsStatusProjectionActivity", projectionQueryRequest);

                if (null != allProjections)
                {
                    // This should be done by fan-out/fan-in
                    List <Task <ProjectionResultsRecord <Get_League_Summary_Definition_Return> > > allProjectionTasks = new List <Task <ProjectionResultsRecord <Get_League_Summary_Definition_Return> > >();

                    // run all the outstanding projections in parallel
                    foreach (Query_Projections_Projection_Return projectionRequest in allProjections)
                    {
                        if (projectionRequest.ProjectionState == Query_Projections_Projection_Return.QueryProjectionState.Queued)
                        {
                            ProjectionRequest projRequest = new ProjectionRequest()
                            {
                                ParentRequestName                 = queryRequest.QueryName,
                                CorrelationIdentifier             = queryRequest.QueryUniqueIdentifier,
                                DomainName                        = "Leagues",
                                AggregateTypeName                 = "League",
                                AggregateInstanceUniqueIdentifier = projectionRequest.Projection.InstanceKey,
                                AsOfDate       = null,
                                ProjectionName = projectionRequest.Projection.ProjectionTypeName
                            };

                            // mark it as in-flight
                            resp = await context.CallActivityAsync <ActivityResponse>("LogQueryProjectionInFlightActivity", projRequest);

                            if (null != resp)
                            {
                                context.SetCustomStatus(resp);
                            }

                            // and start running it...
                            allProjectionTasks.Add(context.CallActivityAsync <ProjectionResultsRecord <Get_League_Summary_Definition_Return> >("RunLeagueSummaryInformationProjectionActivity", projRequest));
                        }
                    }

                    #region Logging
                    if (null != log)
                    {
                        log.LogInformation($"Running {allProjectionTasks.Count } projections in parallel");
                    }
                    #endregion

                    // and persist their results to the query
                    context.SetCustomStatus($"Running {allProjectionTasks.Count } projections in parallel");

                    await Task.WhenAll(allProjectionTasks);

                    #region Logging
                    if (null != log)
                    {
                        log.LogInformation($"Completed running {allProjectionTasks.Count } projections in parallel");
                    }
                    #endregion

                    foreach (var returnValue in allProjectionTasks)
                    {
                        ProjectionResultsRecord <Get_League_Summary_Definition_Return> projectionResponse = returnValue.Result;
                        // add in the extra details
                        projectionResponse.CorrelationIdentifier = queryRequest.QueryUniqueIdentifier;
                        projectionResponse.ParentRequestName     = queryRequest.QueryName;
                        // log the result...
                        resp = await context.CallActivityAsync <ActivityResponse>("LogQueryProjectionResultActivity", projectionResponse);

                        #region Logging
                        if (null != log)
                        {
                            if (null != resp)
                            {
                                log.LogInformation($"{resp.FunctionName} complete: {resp.Message } ");
                            }
                        }
                        #endregion


                        if (null != resp)
                        {
                            context.SetCustomStatus(resp);
                        }
                    }
                }
            }

            return(resp);
        }