public static async Task <ActivityResponse> QueryOutputProcessorOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context, Microsoft.Extensions.Logging.ILogger log) { ActivityResponse response = new ActivityResponse() { FunctionName = "QueryOutputProcessorOrchestrator" }; // Get the Query_Outputs_Request from the context... Query_Outputs_Request request = context.GetInput <Query_Outputs_Request>(); if (null != request) { // Read the outputs for the given query Guid queryGuid; if (Guid.TryParse(request.UniqueIdentifier, out queryGuid)) { // Get the current state of the query... Projection getQueryState = new Projection(Constants.Domain_Query, request.QueryName, queryGuid.ToString(), nameof(Query_Summary_Projection)); if (null != getQueryState) { // 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 from {request.QueryName} : {request.UniqueIdentifier} "); } #endregion List <Task <ActivityResponse> > allOutputTasks = new List <Task <ActivityResponse> >(); if (null != request.Results) { // Create a QueryOutputRecord<object> QueryOutputRecord <object> outputRequest = QueryOutputRecord <object> .Create(request.Results, @"", request.QueryName, queryGuid); foreach (string location in qryOutputs.WebhookTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent by webhook in OutputResultsGetLeagueSummaryQuery"); } #endregion outputRequest.Target = location; // add a task to ouputit it via webhook.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToWebhookActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } foreach (string location in qryOutputs.BlobTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being persisted to a Blob in {response.FunctionName}"); } #endregion outputRequest.Target = location; // add a task to ouputit it via webhook.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToBlobActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } foreach (string location in qryOutputs.ServiceBusTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent out via service bus in {response.FunctionName}"); } #endregion outputRequest.Target = location; // add a task to ouputit it via service bus.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToServiceBusActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } //EventGridTargets foreach (string location in qryOutputs.EventGridTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent out via event grid in {response.FunctionName}"); } #endregion outputRequest.Target = location; // add a task to ouputit it via event grid.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToEventGridActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } foreach (string location in qryOutputs.SignalRTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent out via SignalR in {response.FunctionName}"); } #endregion outputRequest.Target = location; // add a task to ouputit it via SignalR.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToSignalRActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } // TODO: All the other output methods } // Await for all the outputs to have run in parallel... await Task.WhenAll(allOutputTasks); foreach (var returnedResponse in allOutputTasks) { if (returnedResponse.Result.FatalError) { response.FatalError = true; response.Message = returnedResponse.Result.Message; } #region Logging if (null != log) { log.LogDebug($"Sent results to output targets from {returnedResponse.Result.FunctionName} : {returnedResponse.Result.Message } "); } #endregion context.SetCustomStatus(returnedResponse.Result); } } } } } else { response.Message = $"Unable to get outputs request details in sub orchestration {context.InstanceId} "; response.FatalError = true; } return(response); }
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; // If there are outputs set, log them... resp = await context.CallActivityWithRetryAsync <ActivityResponse>("QueryLogOutputTargetActivity", 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); } 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 = "GetLeagueSummaryValidateActivity" }; } 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 = "GetLeagueSummaryQueryProjectionRequestActivity" }; } 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); } } // 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); // Output them to every registered output destination Query_Outputs_Request request = new Query_Outputs_Request() { Results = JObject.FromObject(ret), QueryName = queryRequest.QueryName, UniqueIdentifier = queryRequest.QueryUniqueIdentifier.ToString() }; try { resp = await context.CallSubOrchestratorWithRetryAsync <ActivityResponse>("QueryOutputProcessorOrchestrator", DomainSettings.QueryRetryOptions(), request); } catch (FunctionFailedException ffs) { if (null == resp) { resp = new ActivityResponse() { FunctionName = "QueryOutputProcessorOrchestrator" }; } 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); } } 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; } }