public static async Task <HttpResponseMessage> RunProjectionRun( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequestMessage req, ILogger log) { #region Logging if (null != log) { log.LogDebug("Function triggered HTTP in RunProjection"); } #endregion string parentRequestName; string projectionName; string domainName; string aggregateTypeName; string entityUniqueIdentifier; Nullable <DateTime> asOfDate = null; // Get the parameters from the query parentRequestName = req.GetQueryNameValuePairsExt()[@"ParentRequestName"]; projectionName = req.GetQueryNameValuePairsExt()[@"ProjectionName"]; domainName = req.GetQueryNameValuePairsExt()[@"DomainName"]; aggregateTypeName = req.GetQueryNameValuePairsExt()[@"AggregateTypeName"]; entityUniqueIdentifier = req.GetQueryNameValuePairsExt()[@"EntityUniqueIdentifier"]; string asOfDateString = req.GetQueryNameValuePairsExt()[@"AsOfDate"]; DateTime asOfDateValue; if (DateTime.TryParse(asOfDateString, out asOfDateValue)) { asOfDate = asOfDateValue; } ProjectionRequest request = new ProjectionRequest() { ParentRequestName = parentRequestName, ProjectionName = projectionName, DomainName = domainName, AggregateTypeName = aggregateTypeName, AggregateInstanceUniqueIdentifier = entityUniqueIdentifier, AsOfDate = asOfDate }; ProjectionResultsRecord <object> response = await RunProjection(request, log); if (null != response) { return(req.CreateResponse(HttpStatusCode.OK, response, new System.Net.Http.Formatting.JsonMediaTypeFormatter())); } else { return(req.CreateResponse(HttpStatusCode.BadRequest, $"No projection response for {request }")); } }
public static async Task <IActionResult> RunLeagueSummaryInformationProjection( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req, ILogger log) { #region Logging if (null != log) { log.LogDebug("Function triggered HTTP in RunLeagueSummaryInformationProjectionRun"); } #endregion // Get the query identifier string leagueName = req.Query["LeagueName"]; if (string.IsNullOrWhiteSpace(leagueName)) { string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); dynamic data = JsonConvert.DeserializeObject(requestBody); leagueName = leagueName ?? data?.LeagueName; } ProjectionResultsRecord <Get_League_Summary_Definition_Return> ret = null; string message = $"Running projection for {leagueName}"; ret = await ProcessLeagueSummaryInformationProjection("League_Summary_Information", leagueName, log); if (null != ret) { if (null != ret.Result) { message = $"{leagueName} Location: {ret.Result.Location } incorporated {ret.Result.Date_Incorporated} (Twitter handle:{ret.Result.Twitter_Handle }) "; } } if (string.IsNullOrWhiteSpace(leagueName)) { return(new BadRequestObjectResult($"Please pass a league name to run the projection over")); } else { return((ActionResult) new OkObjectResult(new { leagueName, message, ret })); } }
public static async Task <ActivityResponse> LogQueryProjectionResultActivity( [ActivityTrigger] DurableActivityContext context, ILogger log ) { CQRSAzure.EventSourcing.IWriteContext writeContext = null; // TODO: Pass this as a parameter ActivityResponse resp = new ActivityResponse() { FunctionName = "LogQueryProjectionResultActivity" }; // get the ProjectionResultsRecord ProjectionResultsRecord <object> data = context.GetInput <ProjectionResultsRecord <object> >(); if (null != data) { await QueryLogRecord.LogProjectionResult(data.CorrelationIdentifier, data.ParentRequestName, data.ProjectionName, data.DomainName, data.AggregateTypeName, data.EntityUniqueIdentifier, data.CurrentAsOfDate, data.Result, data.CurrentSequenceNumber, writeContext); resp.Message = $"Saved projection result to query {data.ParentRequestName} - {data.CorrelationIdentifier} "; } else { resp.Message = "Unable to get projection result from context"; resp.FatalError = true; } return(resp); }
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); }
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); }