示例#1
0
        public async Task <IActionResult> ContinueExecutionAsync([Required] string executionId,
                                                                 [Required, FromBody] ContinueExecutionApiModel continueApiModel)
        {
            // Build the execution request context so we can pick up where we left off...

            var erContext = new ExecutionRequestContext <ContinueExecutionApiModel>(continueApiModel)
            {
                Execution = await execRepository.GetExecutionAsync(executionId, userContext.Executor.TenantId)
            };

            // If we can't find the original execution, respond with [404 Not Found]...

            if (erContext.Execution == null)
            {
                return(NotFound($"[{ErrorCodes.ExecutionNotFound}]: Execution [{executionId}] not found."));
            }

            // If we found the execution but we're not expecting any input objects, respond with [400 Bad Request]...

            if (erContext.Execution.Status != ExecutionStatus.PendingInputObjects)
            {
                return(BadRequest($"[{ErrorCodes.UnableToContinue}]: Unable to continue; " +
                                  $"execution [{executionId}] is already [{erContext.Execution.Status}]."));
            }

            // Augment the execution request context with extension, extension version, and execution profile.
            // We're going to need all of this information to build and dispatch the core execution request...

            erContext.Extension = await extensionRepository.GetExtensionAsync(erContext.Execution.ExtensionId);

            erContext.ExtensionVersion = erContext.Extension.GetExtensionVersion(erContext.Execution.ExtensionVersionId);
            erContext.ExecutionProfile = erContext.ExtensionVersion.GetExecutionProfile(erContext.Execution.ExecutionProfileName);

            // Make sure that we have the right input objects and only the right input objects...

            erContext.Execution.ProvidedInputObjects.AddRange(erContext.OriginalRequest.ProvidedInputObjects.Where(pio =>
                                                                                                                   erContext.ExtensionVersion.InputObjects.Any(io => io.Name == pio) &&
                                                                                                                   erContext.Execution.ProvidedInputObjects.Contains(pio) == false));

            var unknownObjects = erContext.OriginalRequest.ProvidedInputObjects
                                 .Where(pio => erContext.Execution.InputObjects.Select(io => io.Name).Contains(pio) == false)
                                 .ToArray();

            var neededObjects = erContext.Execution.InputObjects
                                .Where(io => io.IsRequired && (erContext.OriginalRequest.ProvidedInputObjects.Contains(io.Name) == false))
                                .Select(io => io.Name)
                                .ToArray();

            // If we don't, respond with [400 Bad Request] + detailed error description...

            if (unknownObjects.Any() || neededObjects.Any())
            {
                var errorMessages = new List <string>();

                if (unknownObjects.Any())
                {
                    errorMessages.Add($"[{ErrorCodes.UnknownInputObjects}]: " +
                                      $"The following provided input objects are unknown: [{unknownObjects.ToCommaSeparatedString()}].");
                }

                if (neededObjects.Any())
                {
                    errorMessages.Add($"[{ErrorCodes.MissingInputObjects}]: " +
                                      $"The following input objects are missing: [{neededObjects.ToCommaSeparatedString()}].");
                }

                return(BadRequest(await CreateToContinueApiModelAsync(erContext, errorMessages.ToSpaceSeparatedString())));
            }
            else
            {
                // Otherwise, dispatch the execution request to the execution pipeline and respond back to the client appropriately.
                // For more information on the execution pipeline, see /doc/architecture/execution-pipeline.md.

                return(await ToExecutionRequestRoutedResultAsync(await ExecuteAsync(erContext)));
            }
        }