private async Task UpdateStepResultRecordAsync( RecipeContext recipeContext, bool IsSuccessful, Exception exception = null) { var recipeResult = await _recipeStore.FindByExecutionIdAsync(recipeContext.ExecutionId); if (recipeResult != null) { var recipeStepResult = recipeResult.Steps.FirstOrDefault(step => step.StepId == recipeContext.RecipeStep.Id); if (recipeStepResult != null) { recipeStepResult.IsCompleted = true; recipeStepResult.IsSuccessful = IsSuccessful; recipeStepResult.ErrorMessage = exception?.ToString(); await _recipeStore.UpdateAsync(recipeResult); } } }
public async Task <string> ExecuteAsync(string executionId, RecipeDescriptor recipeDescriptor) { await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.RecipeExecutingAsync(executionId, recipeDescriptor)); try { var parsersForFileExtension = _recipeOptions .RecipeFileExtensions .Where(rfx => Path.GetExtension(rfx.Key) == Path.GetExtension(recipeDescriptor.RecipeFileInfo.PhysicalPath)); using (var stream = recipeDescriptor.RecipeFileInfo.CreateReadStream()) { RecipeResult result = new RecipeResult { ExecutionId = executionId }; List <RecipeStepResult> stepResults = new List <RecipeStepResult>(); foreach (var parserForFileExtension in parsersForFileExtension) { var recipeParser = _recipeParsers.First(x => x.GetType() == parserForFileExtension.Value); await recipeParser.ProcessRecipeAsync(stream, (recipe, recipeStep) => { // TODO, create Result prior to run stepResults.Add(new RecipeStepResult { ExecutionId = executionId, RecipeName = recipeDescriptor.Name, StepId = recipeStep.Id, StepName = recipeStep.Name }); return(Task.CompletedTask); }); } result.Steps = stepResults; await _recipeStore.UpdateAsync(result); } using (var stream = recipeDescriptor.RecipeFileInfo.CreateReadStream()) { foreach (var parserForFileExtension in parsersForFileExtension) { var recipeParser = _recipeParsers.First(x => x.GetType() == parserForFileExtension.Value); await recipeParser.ProcessRecipeAsync(stream, async (recipe, recipeStep) => { var shellContext = _orchardHost.GetOrCreateShellContext(_shellSettings); using (var scope = shellContext.CreateServiceScope()) { if (!shellContext.IsActivated) { var eventBus = scope.ServiceProvider.GetService <IEventBus>(); await eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatingAsync()); await eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatedAsync()); shellContext.IsActivated = true; } var recipeStepExecutor = scope.ServiceProvider.GetRequiredService <IRecipeStepExecutor>(); if (_applicationLifetime.ApplicationStopping.IsCancellationRequested) { throw new OrchardException(T["Recipe cancelled, application is restarting"]); } await recipeStepExecutor.ExecuteAsync(executionId, recipeStep); } // The recipe execution might have invalidated the shell by enabling new features, // so the deferred tasks need to run on an updated shell context if necessary. shellContext = _orchardHost.GetOrCreateShellContext(_shellSettings); using (var scope = shellContext.CreateServiceScope()) { var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>(); // The recipe might have added some deferred tasks to process if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks) { var taskContext = new DeferredTaskContext(scope.ServiceProvider); await deferredTaskEngine.ExecuteTasksAsync(taskContext); } } }); } } await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.RecipeExecutedAsync(executionId, recipeDescriptor)); return(executionId); } catch (Exception) { await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.ExecutionFailedAsync(executionId, recipeDescriptor)); throw; } }
public async Task <string> ExecuteAsync(string executionId, RecipeDescriptor recipeDescriptor, object environment) { await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.RecipeExecutingAsync(executionId, recipeDescriptor)); try { _environmentMethodProvider = new ParametersMethodProvider(environment); var result = new RecipeResult { ExecutionId = executionId }; await _recipeStore.CreateAsync(result); using (StreamReader file = File.OpenText(recipeDescriptor.RecipeFileInfo.PhysicalPath)) { using (var reader = new JsonTextReader(file)) { // Go to Steps, then iterate. while (reader.Read()) { if (reader.Path == "variables") { reader.Read(); var variables = JObject.Load(reader); _variablesMethodProvider = new VariablesMethodProvider(variables); } if (reader.Path == "steps" && reader.TokenType == JsonToken.StartArray) { while (reader.Read() && reader.Depth > 1) { if (reader.Depth == 2) { var child = JObject.Load(reader); var recipeStep = new RecipeExecutionContext { Name = child.Value <string>("name"), Step = child, ExecutionId = executionId, Environment = environment }; var stepResult = new RecipeStepResult { StepName = recipeStep.Name }; result.Steps.Add(stepResult); await _recipeStore.UpdateAsync(result); ExceptionDispatchInfo capturedException = null; try { await ExecuteStepAsync(recipeStep); stepResult.IsSuccessful = true; } catch (Exception e) { stepResult.IsSuccessful = false; stepResult.ErrorMessage = e.ToString(); // Because we can't do some async processing the in catch or finally // blocks, we store the exception to throw it later. capturedException = ExceptionDispatchInfo.Capture(e); } stepResult.IsCompleted = true; await _recipeStore.UpdateAsync(result); if (stepResult.IsSuccessful == false) { capturedException.Throw(); } } } } } } } await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.RecipeExecutedAsync(executionId, recipeDescriptor)); return(executionId); } catch (Exception) { await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.ExecutionFailedAsync(executionId, recipeDescriptor)); throw; } }