From 0c6326bafdf4141e2472273eb467e0fa13729dfe Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 4 Aug 2015 15:03:47 +0100 Subject: [PATCH] Improved recipe import/reset execution by pausing sweep generator. This prevents active background tasks from accessing tables that may no longer be there (in the case of a full site reset) by pausing the sweep generator. To ensure that the sweep generator is resumed after the recipe has been executed, a new ActivateSweepGeneratorStep is enqueued at the end of the recipe execution. --- .../ImportActions/ExecuteRecipeAction.cs | 39 +++++++++++++++---- .../Orchard.Recipes/Orchard.Recipes.csproj | 1 + .../Executors/ActivateSweepGeneratorStep.cs | 20 ++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.Recipes/Providers/Executors/ActivateSweepGeneratorStep.cs diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Providers/ImportActions/ExecuteRecipeAction.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Providers/ImportActions/ExecuteRecipeAction.cs index e42f0fa06..9b52d8678 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Providers/ImportActions/ExecuteRecipeAction.cs +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Providers/ImportActions/ExecuteRecipeAction.cs @@ -4,14 +4,15 @@ using System.IO; using System.Linq; using System.Xml.Linq; using Orchard.ContentManagement; +using Orchard.Data; using Orchard.Environment.Configuration; -using Orchard.Environment.Features; using Orchard.ImportExport.Models; using Orchard.ImportExport.Services; using Orchard.ImportExport.ViewModels; using Orchard.Mvc; using Orchard.Recipes.Models; using Orchard.Recipes.Services; +using Orchard.Tasks; using Orchard.UI.Notify; namespace Orchard.ImportExport.Providers.ImportActions { @@ -19,31 +20,37 @@ namespace Orchard.ImportExport.Providers.ImportActions { private readonly IOrchardServices _orchardServices; private readonly ISetupService _setupService; private readonly ShellSettings _shellSettings; - private readonly IFeatureManager _featureManager; private readonly IEnumerable _recipeExecutionSteps; private readonly IRecipeParser _recipeParser; private readonly IRecipeExecutor _recipeExecutor; private readonly IDatabaseManager _databaseManager; + private readonly ISweepGenerator _sweepGenerator; + private readonly IRecipeStepQueue _recipeStepQueue; + private readonly IRepository _recipeStepResultRepository; public ExecuteRecipeAction( IOrchardServices orchardServices, ISetupService setupService, ShellSettings shellSettings, - IFeatureManager featureManager, IEnumerable recipeExecutionSteps, IRecipeParser recipeParser, IRecipeExecutor recipeExecutor, - IDatabaseManager databaseManager) { + IDatabaseManager databaseManager, + ISweepGenerator sweepGenerator, + IRecipeStepQueue recipeStepQueue, + IRepository recipeStepResultRepository) { _orchardServices = orchardServices; _setupService = setupService; _shellSettings = shellSettings; - _featureManager = featureManager; _recipeExecutionSteps = recipeExecutionSteps; _recipeParser = recipeParser; _recipeExecutor = recipeExecutor; _databaseManager = databaseManager; - } + _sweepGenerator = sweepGenerator; + _recipeStepQueue = recipeStepQueue; + _recipeStepResultRepository = recipeStepResultRepository; + } public override string Name { get { return "ExecuteRecipe"; } } @@ -144,13 +151,29 @@ namespace Orchard.ImportExport.Providers.ImportActions { // Sets the request timeout to 10 minutes to give enough time to execute custom recipes. _orchardServices.WorkContext.HttpContext.Server.ScriptTimeout = 600; + // Suspend background task execution. + _sweepGenerator.Terminate(); + + // Import or setup using the specified recipe. var executionId = ResetSite ? Setup(recipeDocument) : ExecuteRecipe(recipeDocument); if(executionId == null) { _orchardServices.Notifier.Warning(T("The recipe contained no steps. No work was scheduled.")); + _sweepGenerator.Activate(); return; } + // Resume background tasks once import/setup completes. + var recipe = _recipeParser.ParseRecipe(recipeDocument); + var activateSweepGeneratorStep = new RecipeStep(Guid.NewGuid().ToString("N"), recipe.Name, "ActivateSweepGenerator", new XElement("ActivateSweepGenerator")); + _recipeStepQueue.Enqueue(executionId, activateSweepGeneratorStep); + _recipeStepResultRepository.Create(new RecipeStepResultRecord { + ExecutionId = executionId, + RecipeName = recipe.Name, + StepId = activateSweepGeneratorStep.Id, + StepName = activateSweepGeneratorStep.Name + }); + context.ExecutionId = executionId; context.RecipeDocument = recipeDocument; } @@ -172,7 +195,9 @@ namespace Orchard.ImportExport.Providers.ImportActions { DropTenantDatabaseTables(); // Execute Setup. - return _setupService.Setup(setupContext); + var executionId = _setupService.Setup(setupContext); + + return executionId; } private string ExecuteRecipe(XDocument recipeDocument) { diff --git a/src/Orchard.Web/Modules/Orchard.Recipes/Orchard.Recipes.csproj b/src/Orchard.Web/Modules/Orchard.Recipes/Orchard.Recipes.csproj index ee0ee039b..f0731e905 100644 --- a/src/Orchard.Web/Modules/Orchard.Recipes/Orchard.Recipes.csproj +++ b/src/Orchard.Web/Modules/Orchard.Recipes/Orchard.Recipes.csproj @@ -91,6 +91,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Recipes/Providers/Executors/ActivateSweepGeneratorStep.cs b/src/Orchard.Web/Modules/Orchard.Recipes/Providers/Executors/ActivateSweepGeneratorStep.cs new file mode 100644 index 000000000..d7f83d8dd --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Recipes/Providers/Executors/ActivateSweepGeneratorStep.cs @@ -0,0 +1,20 @@ +using Orchard.Recipes.Models; +using Orchard.Recipes.Services; +using Orchard.Tasks; + +namespace Orchard.Recipes.Providers.Executors { + public class ActivateSweepGeneratorStep : RecipeExecutionStep { + private readonly ISweepGenerator _sweepGenerator; + + public ActivateSweepGeneratorStep(ISweepGenerator sweepGenerator, RecipeExecutionLogger logger) + : base(logger) { + _sweepGenerator = sweepGenerator; + } + + public override string Name { get { return "ActivateSweepGenerator"; } } + + public override void Execute(RecipeExecutionContext context) { + _sweepGenerator.Activate(); + } + } +}