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; } }
public async Task <string> ExecuteAsync(string executionId, RecipeDescriptor recipeDescriptor, object environment, CancellationToken cancellationToken) { await _recipeEventHandlers.InvokeAsync((handler, executionId, recipeDescriptor) => handler.RecipeExecutingAsync(executionId, recipeDescriptor), executionId, recipeDescriptor, _logger); try { _environmentMethodProvider = new ParametersMethodProvider(environment); _configurationMethodProvider = new ConfigurationMethodProvider(_shellSettings.ShellConfiguration); var result = new RecipeResult { ExecutionId = executionId }; using (var stream = recipeDescriptor.RecipeFileInfo.CreateReadStream()) { using (var file = new StreamReader(stream)) { using (var reader = new JsonTextReader(file)) { // Go to Steps, then iterate. while (await reader.ReadAsync()) { if (reader.Path == "variables") { await reader.ReadAsync(); var variables = await JObject.LoadAsync(reader); _variablesMethodProvider = new VariablesMethodProvider(variables); } if (reader.Path == "steps" && reader.TokenType == JsonToken.StartArray) { while (await reader.ReadAsync() && reader.Depth > 1) { if (reader.Depth == 2) { var child = await JObject.LoadAsync(reader); var recipeStep = new RecipeExecutionContext { Name = child.Value <string>("name"), Step = child, ExecutionId = executionId, Environment = environment, RecipeDescriptor = recipeDescriptor }; if (cancellationToken.IsCancellationRequested) { _logger.LogError("Recipe interrupted by cancellation token."); return(null); } var stepResult = new RecipeStepResult { StepName = recipeStep.Name }; result.Steps.Add(stepResult); 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; if (stepResult.IsSuccessful == false) { capturedException.Throw(); } if (recipeStep.InnerRecipes != null) { foreach (var descriptor in recipeStep.InnerRecipes) { var innerExecutionId = Guid.NewGuid().ToString(); await ExecuteAsync(innerExecutionId, descriptor, environment, cancellationToken); } } } } } } } } } await _recipeEventHandlers.InvokeAsync((handler, executionId, recipeDescriptor) => handler.RecipeExecutedAsync(executionId, recipeDescriptor), executionId, recipeDescriptor, _logger); return(executionId); } catch (Exception) { await _recipeEventHandlers.InvokeAsync((handler, executionId, recipeDescriptor) => handler.ExecutionFailedAsync(executionId, recipeDescriptor), executionId, recipeDescriptor, _logger); throw; } }