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; } Get_League_Summary_Definition_Return ret = null; string message = $"Running projection for {leagueName}"; try { ret = await ProcessLeagueSummaryInformationProjection("League_Summary_Information", leagueName, log); } catch (Exception ex) { message = ex.ToString(); } if (null != ret) { message = $"{leagueName} Location: {ret.Location } incorporated {ret.Date_Incorporated} (Twitter handle:{ret.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 <HttpResponseMessage> GetLeagueSummaryGetResultsRun( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequestMessage req, ILogger log) { #region Logging if (null != log) { log.LogDebug("Function triggered HTTP in GetLeagueSummaryQueryProjectionsRequest"); } #endregion // Get the query identifier string queryId = req.GetQueryNameValuePairsExt()[@"QueryId"]; Get_League_Summary_Definition_Return value = null; string results = $"No results for {queryId}"; if (queryId == null) { // Get request body dynamic data = await req.Content.ReadAsAsync <object>(); queryId = data?.QueryId; } value = await GetLeagueSummaryGetResults("get-league-summary", queryId, log); if (null != value) { results = $"Results from {queryId} - {value.LeagueName} incorporated {value.Date_Incorporated} at {value.Location} ({value.Twitter_Handle})"; } return(queryId == null ? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a queryId on the query string or in the request body") : req.CreateResponse(HttpStatusCode.OK, results)); }
/// <summary> /// Send out the results for a completed "Get-League-Summary" query /// </summary> /// <param name="queryId"> /// Unique identifier of the query for which we want to send out the results /// </param> /// <param name="log"> /// Trace target for logging the outcomes of this operation /// </param> private static async Task <ActivityResponse> OutputResultsGetLeagueSummaryQuery( string queryName, string queryId, ILogger log) { ActivityResponse ret = new ActivityResponse() { FunctionName = "OutputResultsGetLeagueSummaryQuery" }; Guid queryGuid; if (Guid.TryParse(queryId, out queryGuid)) { // Get the current state of the query... Projection getQueryState = new Projection(@"Query", queryName, queryGuid.ToString(), nameof(Query_Summary_Projection)); if (null != getQueryState) { #region Logging if (null != log) { log.LogDebug($"Projection processor created in OutputResultsGetLeagueSummaryQuery"); } #endregion // Run the query summary projection Query_Summary_Projection qryProjection = new Query_Summary_Projection(log); await getQueryState.Process(qryProjection); if ((qryProjection.CurrentSequenceNumber > 0) || (qryProjection.ProjectionValuesChanged())) { // Process the query state as is now... #region Logging if (null != log) { log.LogDebug($"Query { qryProjection.QueryName } projection run for {queryGuid } in OutputResultsGetLeagueSummaryQuery"); } #endregion // Ignore queries in an invalid state or not yet validated... if (qryProjection.CurrentState == Query_Summary_Projection.QueryState.Invalid) { // No need to run projections on an invalid query #region Logging if (null != log) { log.LogWarning($"Query {queryGuid} state is {qryProjection.CurrentState} so no output processed in OutputResultsGetLeagueSummaryQuery"); } #endregion ret.Message = $"Query {queryGuid} state is {qryProjection.CurrentState} so no output processed in OutputResultsGetLeagueSummaryQuery"; ret.FatalError = true; return(ret); } // Check all the projections have been run.. Query_Projections_Projection qryProjectionState = new Query_Projections_Projection(log); await getQueryState.Process(qryProjectionState); if ((qryProjectionState.CurrentSequenceNumber > 0) || (qryProjectionState.ProjectionValuesChanged())) { if (qryProjectionState.UnprocessedRequests.Count == 0) { if (qryProjectionState.ProcessedRequests.Count > 0) { // Turn the projections into a query return (This could include a collate step) Get_League_Summary_Definition_Return projectionReturn = new Get_League_Summary_Definition_Return(queryGuid, qryProjectionState.ProcessedRequests[0].AggregateInstanceKey); if (qryProjectionState.ProcessedRequests[0].ProjectionTypeName == typeof(Leagues.League.projection.League_Summary_Information).Name) { Leagues.League.projection.League_Summary_Information projectionResult = ((Newtonsoft.Json.Linq.JObject)qryProjectionState.ProcessedRequests[0].ReturnedValue).ToObject <Leagues.League.projection.League_Summary_Information>(); if (null != projectionResult) { projectionReturn.Location = projectionResult.Location; projectionReturn.Date_Incorporated = projectionResult.Date_Incorporated; projectionReturn.Twitter_Handle = projectionResult.Twitter_Handle; } else { #region Logging if (null != log) { log.LogError($"Unable to convert {qryProjectionState.ProcessedRequests[0].ReturnedValue} to {nameof(Leagues.League.projection.League_Summary_Information)} in OutputResultsGetLeagueSummaryQuery"); } #endregion } } // Get all the output targets Query_Outputs_Projection qryOutputs = new Query_Outputs_Projection(log); await getQueryState.Process(qryOutputs); if ((qryOutputs.CurrentSequenceNumber > 0) || (qryOutputs.ProjectionValuesChanged())) { #region Logging if (null != log) { log.LogDebug($"Sending results to output targets in OutputResultsGetLeagueSummaryQuery"); } #endregion foreach (string location in qryOutputs.Targets.Keys) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - type {qryOutputs.Targets[location]} in OutputResultsGetLeagueSummaryQuery"); } #endregion // Send the output to the location... QueryLogRecord.SendOutput(location, qryOutputs.Targets[location], ret); } ret.Message = $"Sent results to output targets ({qryOutputs.Targets.Keys.Count}) in OutputResultsGetLeagueSummaryQuery"; return(ret); } else { // No outputs set #region Logging if (null != log) { log.LogWarning($"No output targets found in OutputResultsGetLeagueSummaryQuery"); } #endregion ret.Message = $"No output targets found in OutputResultsGetLeagueSummaryQuery"; return(ret); } } else { // No processed projections found #region Logging if (null != log) { log.LogWarning($"Query {queryGuid} state is has no processed projections so no output processed in OutputResultsGetLeagueSummaryQuery"); } #endregion ret.Message = $"Query {queryGuid} state is has no processed projections so no output processed in OutputResultsGetLeagueSummaryQuery"; return(ret); } } else { #region Logging if (null != log) { log.LogWarning($"Query {queryGuid} still has unprocessed projections so no output processed in OutputResultsGetLeagueSummaryQuery"); } #endregion ret.Message = $"Query {queryGuid} still has unprocessed projections so no output processed in OutputResultsGetLeagueSummaryQuery"; return(ret); } } else { ret.Message = $"Projection run but has no results"; ret.FatalError = true; return(ret); } } } } ret.Message = $"Query identifier blank or not set when running OutputResultsGetLeagueSummaryQuery"; ret.FatalError = true; return(ret); }
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; } }
private static async Task <ProjectionResultsRecord <Get_League_Summary_Definition_Return> > ProcessLeagueSummaryInformationProjection( string projectionName, string leagueName, ILogger log) { try { Projection leagueEvents = new Projection("Leagues", "League", leagueName, projectionName); if (null != leagueEvents) { Leagues.League.projection.League_Summary_Information prjLeagueInfo = new Leagues.League.projection.League_Summary_Information(); await leagueEvents.Process(prjLeagueInfo); if (null != prjLeagueInfo) { if ((prjLeagueInfo.CurrentSequenceNumber > 0) || (prjLeagueInfo.ProjectionValuesChanged())) { Get_League_Summary_Definition_Return value = new Get_League_Summary_Definition_Return(Guid.Empty, leagueName) { Date_Incorporated = prjLeagueInfo.Date_Incorporated, Location = prjLeagueInfo.Location, Twitter_Handle = prjLeagueInfo.Twitter_Handle }; return(new ProjectionResultsRecord <Get_League_Summary_Definition_Return>() { CurrentAsOfDate = prjLeagueInfo.CurrentAsOfDate, CurrentSequenceNumber = (int)prjLeagueInfo.CurrentSequenceNumber, AggregateTypeName = leagueEvents.AggregateTypeName, DomainName = leagueEvents.DomainName, EntityUniqueIdentifier = leagueEvents.AggregateInstanceKey, Result = value }); } } } else { #region Logging if (null != log) { log.LogError("Unable to create league events projection"); } #endregion } } catch (Exception ex) { #region Logging if (null != log) { log.LogError($"Unable to perform projection {ex.Message}"); } #endregion } return(null); }
/// <summary> /// Send out the results for a completed "Get-League-Summary" query /// </summary> /// <param name="queryId"> /// Unique identifier of the query for which we want to send out the results /// </param> /// <param name="log"> /// Trace target for logging the outcomes of this operation /// </param> private static async Task <ActivityResponse> OutputResultsGetLeagueSummaryQuery( string queryName, string queryId, ILogger log) { ActivityResponse ret = new ActivityResponse() { FunctionName = "OutputResultsGetLeagueSummaryQuery" }; Guid queryGuid; if (Guid.TryParse(queryId, out queryGuid)) { // Get the current state of the query... Projection getQueryState = new Projection(Constants.Domain_Query, queryName, queryGuid.ToString(), nameof(Query_Summary_Projection)); if (null != getQueryState) { #region Logging if (null != log) { log.LogDebug($"Projection processor created in OutputResultsGetLeagueSummaryQuery"); } #endregion // Run the query summary projection Query_Summary_Projection qryProjection = new Query_Summary_Projection(log); await getQueryState.Process(qryProjection); if ((qryProjection.CurrentSequenceNumber > 0) || (qryProjection.ProjectionValuesChanged())) { // Process the query state as is now... #region Logging if (null != log) { log.LogDebug($"Query { qryProjection.QueryName } projection run for {queryGuid } in OutputResultsGetLeagueSummaryQuery"); } #endregion // Ignore queries in an invalid state or not yet validated... if (qryProjection.CurrentState == Query_Summary_Projection.QueryState.Invalid) { // No need to run projections on an invalid query #region Logging if (null != log) { log.LogWarning($"Query {queryGuid} state is {qryProjection.CurrentState} so no output processed in OutputResultsGetLeagueSummaryQuery"); } #endregion ret.Message = $"Query {queryGuid} state is {qryProjection.CurrentState} so no output processed in OutputResultsGetLeagueSummaryQuery"; ret.FatalError = true; return(ret); } // Check all the projections have been run.. Query_Projections_Projection qryProjectionState = new Query_Projections_Projection(log); await getQueryState.Process(qryProjectionState); if ((qryProjectionState.CurrentSequenceNumber > 0) || (qryProjectionState.ProjectionValuesChanged())) { if (qryProjectionState.UnprocessedRequests.Count == 0) { if (qryProjectionState.ProcessedRequests.Count > 0) { // Turn the projections into a query return (This could include a collate step) Get_League_Summary_Definition_Return projectionReturn = new Get_League_Summary_Definition_Return(queryGuid, qryProjectionState.ProcessedRequests[0].AggregateInstanceKey); if (qryProjectionState.ProcessedRequests[0].ProjectionTypeName == typeof(Leagues.League.projection.League_Summary_Information).Name) { dynamic projectionResult = (qryProjectionState.ProcessedRequests[0].ReturnedValue); if (null != projectionResult) { projectionReturn.Location = projectionResult.Location; projectionReturn.Date_Incorporated = projectionResult.Date_Incorporated; projectionReturn.Twitter_Handle = projectionResult.Twitter_Handle; } else { #region Logging if (null != log) { log.LogError($"Unable to convert {qryProjectionState.ProcessedRequests[0].ReturnedValue} to {nameof(Leagues.League.projection.League_Summary_Information)} in OutputResultsGetLeagueSummaryQuery"); } #endregion } } // Call the outputs processing sub-orchestration // Get all the output targets Query_Outputs_Projection qryOutputs = new Query_Outputs_Projection(log); await getQueryState.Process(qryOutputs); if ((qryOutputs.CurrentSequenceNumber > 0) || (qryOutputs.ProjectionValuesChanged())) { #region Logging if (null != log) { log.LogDebug($"Sending results to output targets in OutputResultsGetLeagueSummaryQuery"); } #endregion foreach (string location in qryOutputs.WebhookTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent by webhook in OutputResultsGetLeagueSummaryQuery"); } #endregion if (null != projectionReturn) { var payloadAsJSON = new StringContent(JsonConvert.SerializeObject(projectionReturn)); using (var client = new HttpClient()) { var response = await client.PostAsync(location, payloadAsJSON); if (!response.IsSuccessStatusCode) { ret.Message = $"Failed to send output to {location} webhook - {response.StatusCode} : {response.ReasonPhrase} "; #region Logging if (null != log) { log.LogError($"{ret.FunctionName } : {ret.Message}"); } #endregion } } } } foreach (string location in qryOutputs.EventGridTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent by event grid message in OutputResultsGetLeagueSummaryQuery"); } #endregion } foreach (string location in qryOutputs.BlobTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being persisted as a blob in OutputResultsGetLeagueSummaryQuery"); } #endregion } foreach (string location in qryOutputs.DurableFunctionOrchestrationTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being used to trigger a durable function to wake up in OutputResultsGetLeagueSummaryQuery"); } #endregion } ret.Message = $"Sent results to output targets ({qryOutputs.Targets.Keys.Count}) in OutputResultsGetLeagueSummaryQuery"; return(ret); } else { // No outputs set #region Logging if (null != log) { log.LogWarning($"No output targets found in OutputResultsGetLeagueSummaryQuery"); } #endregion ret.Message = $"No output targets found in OutputResultsGetLeagueSummaryQuery"; return(ret); } } else { // No processed projections found #region Logging if (null != log) { log.LogWarning($"Query {queryGuid} state is has no processed projections so no output processed in OutputResultsGetLeagueSummaryQuery"); } #endregion ret.Message = $"Query {queryGuid} state is has no processed projections so no output processed in OutputResultsGetLeagueSummaryQuery"; return(ret); } } else { #region Logging if (null != log) { log.LogWarning($"Query {queryGuid} still has unprocessed projections so no output processed in OutputResultsGetLeagueSummaryQuery"); } #endregion ret.Message = $"Query {queryGuid} still has unprocessed projections so no output processed in OutputResultsGetLeagueSummaryQuery"; return(ret); } } else { ret.Message = $"Projection run but has no results"; ret.FatalError = true; return(ret); } } } } ret.Message = $"Query identifier blank or not set when running OutputResultsGetLeagueSummaryQuery"; ret.FatalError = true; return(ret); }
/// <summary> /// Get the league summary results as they currently are in this query /// </summary> /// <returns></returns> private static async Task <Get_League_Summary_Definition_Return> GetLeagueSummaryGetResults(string queryName, string queryId, ILogger log) { Guid queryGuid; if (Guid.TryParse(queryId, out queryGuid)) { // Get the current state of the query... Projection getQueryState = new Projection(Constants.Domain_Query, queryName, queryGuid.ToString(), nameof(Query_Summary_Projection)); if (null != getQueryState) { #region Logging if (null != log) { log.LogDebug($"Projection processor created in OutputResultsGetLeagueSummaryQuery"); } #endregion // Run the query summary projection Query_Summary_Projection qryProjection = new Query_Summary_Projection(log); await getQueryState.Process(qryProjection); if ((qryProjection.CurrentSequenceNumber > 0) || (qryProjection.ProjectionValuesChanged())) { // Process the query state as is now... #region Logging if (null != log) { log.LogDebug($"Query { qryProjection.QueryName } projection run for {queryGuid } in OutputResultsGetLeagueSummaryQuery"); } #endregion // Ignore queries in an invalid state or not yet validated... if (qryProjection.CurrentState == Query_Summary_Projection.QueryState.Invalid) { // No need to run projections on an invalid query #region Logging if (null != log) { log.LogWarning($"Query {queryGuid} state is {qryProjection.CurrentState} so no output processed in OutputResultsGetLeagueSummaryQuery"); } #endregion return(null); } // Check all the projections have been run.. Query_Projections_Projection qryProjectionState = new Query_Projections_Projection(log); await getQueryState.Process(qryProjectionState); if ((qryProjectionState.CurrentSequenceNumber > 0) || (qryProjectionState.ProjectionValuesChanged())) { if (qryProjectionState.UnprocessedRequests.Count == 0) { if (qryProjectionState.ProcessedRequests.Count > 0) { // Turn the projections into a query return (This could include a collate step) Get_League_Summary_Definition_Return ret = new Get_League_Summary_Definition_Return(queryGuid, qryProjectionState.ProcessedRequests[0].AggregateInstanceKey); if (qryProjectionState.ProcessedRequests[0].ProjectionTypeName == typeof(Leagues.League.projection.League_Summary_Information).Name) { dynamic projectionResult = (qryProjectionState.ProcessedRequests[0].ReturnedValue); if (null != projectionResult) { ret.Location = projectionResult.Location; ret.Date_Incorporated = projectionResult.Date_Incorporated; ret.Twitter_Handle = projectionResult.Twitter_Handle; return(ret); } else { #region Logging if (null != log) { log.LogError($"Unable to convert {qryProjectionState.ProcessedRequests[0].ReturnedValue} to {nameof(Leagues.League.projection.League_Summary_Information)} in OutputResultsGetLeagueSummaryQuery"); } #endregion } } } else { // No processed projections found #region Logging if (null != log) { log.LogWarning($"Query {queryGuid} state is has no processed projections so no output processed in OutputResultsGetLeagueSummaryQuery"); } #endregion } } else { #region Logging if (null != log) { log.LogWarning($"Query {queryGuid} still has unprocessed projections so no output processed in OutputResultsGetLeagueSummaryQuery"); } #endregion } } } } } return(null); }