private Core.Models.Execution ApplyExecutionContext(Core.Models.ExecutionContext execContext, Core.Models.Execution execution) { execution.LastUpdatedDateTimeUtc = DateTime.UtcNow; execution.PercentComplete = execContext.PercentComplete; if (execContext.ProvidedOutputObjects != null) { execution.ProvidedInputObjects.AddRange( execContext.ProvidedInputObjects.Except(execution.ProvidedInputObjects)); } if (execContext.ProvidedOutputObjects != null) { execution.ProvidedOutputObjects.AddRange( execContext.ProvidedOutputObjects.Except(execution.ProvidedOutputObjects)); } execution.ResultData = (execContext.ResultData ?? execution.ResultData); execution.Status = execContext.Status; execution.StatusMessage = execContext.StatusMessage; execution.ExecutionTimeoutDateTimeUtc = execContext.ExecutionTimeoutDateTimeUtc.GetValueOrDefault(); if (execContext.ValidationErrors != null) { execution.ValidationErrors.AddRange(execContext.ValidationErrors); } return(execution); }
public async Task RouteRequestAsync_ServiceWithGivenExecutionModelName_ShouldRouteSuccessfully() { const string modelName = "expected-model/v1"; var mockProcessor = new Mock<IExecutionProcessor>(); var mockServiceProvider = new Mock<IServiceProvider>(); var processorFactory = new NamedServiceFactory<IExecutionProcessor>( new Dictionary<string, Func<IServiceProvider, IExecutionProcessor>> { [modelName] = sp => mockProcessor.Object }); var execRequest = new ExecutionRequest { ExecutionId = Guid.NewGuid().ToString(), ExecutionModelName = modelName }; var execContext = new Core.Models.ExecutionContext { ExecutionId = execRequest.ExecutionId, Status = ExecutionStatus.Succeeded }; mockProcessor.Setup(ep => ep.ProcessRequestAsync(execRequest, CancellationToken.None)) .Returns(Task.FromResult(execContext)); var execRequestRouter = new ExecutionRequestRouter(processorFactory, mockServiceProvider.Object); var actualExecContext = await execRequestRouter.RouteRequestAsync(execRequest, CancellationToken.None); actualExecContext.Should().NotBeNull(); actualExecContext.Should().Be(execContext); }
private async Task <Core.Models.ExecutionContext> ExecuteAsync <T>(Core.Models.ExecutionContext execContext, T httpExecRequest, HttpExtensionSettings httpSettings) { logger.LogInformation($"Posting execution request [{execContext.ExecutionId}] to [{httpSettings.ExecutionUrl}]..."); // POST the request to the extension... var httpExecResponse = await this.jsonHttpClient.PostAsync <HttpExecutionResponse>( httpSettings.ExecutionUrl, httpExecRequest); // Gather all the appropriate information returned from the extension... execContext.ResultData = httpExecResponse.Content?.ResponseData; execContext.ProvidedOutputObjects = httpExecResponse.Content?.ProvidedOutputObjects; execContext.ValidationErrors = httpExecResponse.Content?.ValidationErrors?.Select(ve => ve.ToCoreModel()).ToList(); switch (httpExecResponse.StatusCode) { // If the extension responded with a [202 Accepted], the execution is long-running. Mark the execution as [Processing]. // The extension is expected to call back to the execution API with status updates. case HttpStatusCode.Accepted: logger.LogInformation($"Execution [{execContext.ExecutionId}] is long-running."); execContext.UpdateStatus(ExecutionStatus.Processing); break; // If the extension responded with a [200 OK], execution was succesful. Mark the execution as such. case HttpStatusCode.OK: logger.LogInformation($"Execution [{execContext.ExecutionId}] complete."); execContext.UpdateStatus(ExecutionStatus.Succeeded); break; // If the extension responded with a [400 Bad Request], either we called the extension wrong OR the client // called the extension wrong. The extension may have provided further information as [validationErrors]. // If [validationErrors] were provided, mark the execution as [ValidationFailed]. // If [validationErrors] were not provided, something else went wrong, so mark the execution as [Failed]. case HttpStatusCode.BadRequest: logger.LogWarning($"Execution request [{execContext.ExecutionId}] is invalid."); ProcessBadRequest(execContext, httpExecResponse.Content); break; // The extension responded with a status code that we didn't expect. Throw an exception... default: throw new HttpRequestException($"Extension returned an unexpected status code: [{httpExecResponse.StatusCode}]."); } return(execContext); }
private Core.Models.ExecutionContext ProcessBadRequest(Core.Models.ExecutionContext execContext, HttpExecutionResponse httpExecResponse) { execContext.ValidationErrors = httpExecResponse?.ValidationErrors.Select(e => e.ToCoreModel()).ToList(); if (execContext.ValidationErrors.Any()) { return(execContext.UpdateStatus(ExecutionStatus.ValidationFailed)); } else { throw new HttpRequestException($"Extension returned an unexpected status code: [{HttpStatusCode.BadRequest}]."); } }
private async Task <Core.Models.ExecutionContext> ValidateAsync <T>(Core.Models.ExecutionContext execContext, T httpExecRequest, HttpExtensionSettings httpSettings) { logger.LogInformation($"Posting execution validation request [{execContext.ExecutionId}] to [{httpSettings.ValidationUrl}]..."); // POST the validation request to the extension... var httpExecResponse = await this.jsonHttpClient.PostAsync <HttpExecutionResponse>( httpSettings.ValidationUrl, httpExecRequest); // Grab any validation errors... execContext.ValidationErrors = httpExecResponse.Content?.ValidationErrors?.Select(ve => ve.ToCoreModel()).ToList(); switch (httpExecResponse.StatusCode) { // If the extension responded with a [200 OK], mark the execution [ValidationSucceeded]. case HttpStatusCode.OK: logger.LogInformation($"Execution request [{execContext.ExecutionId}] is valid."); execContext.UpdateStatus(ExecutionStatus.ValidationSucceeded); break; // If the extension responded with a [400 Bad Request], either we called the extension wrong OR the client // called the extension wrong. The extension may have provided further information as [validationErrors]. // If [validationErrors] were provided, mark the execution as [ValidationFailed]. // If [validationErrors] were not provided, something else went wrong, so mark the execution as [Failed]. case HttpStatusCode.BadRequest: logger.LogInformation($"Execution request [{execContext.ExecutionId}] is invalid."); ProcessBadRequest(execContext, httpExecResponse.Content); break; // The extension responded with a status code that we didn't expect. Throw an exception... default: throw new HttpRequestException($"Extension returned an unexpected status code: [{httpExecResponse.StatusCode}]."); } return(execContext); }