mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Added support for multiple recipe steps of the same type and added unit tests.
Enables execution of multiple child recipes in a particular sequence. This is useful for the RecipesStep for example, where you want to execute a child recipe first, then execute some commands and import some content, then execute a second child recipe.
This commit is contained in:
@@ -159,6 +159,7 @@
|
||||
<Compile Include="Packaging\Services\FileBasedProjectSystemTests.cs" />
|
||||
<Compile Include="Packaging\Services\FolderUpdaterTests.cs" />
|
||||
<Compile Include="Packaging\Services\PackageInstallerTests.cs" />
|
||||
<Compile Include="Recipes\RecipeHandlers\RecipeParserTest.cs" />
|
||||
<Compile Include="Recipes\RecipeHandlers\RecipeExecutionStepHandlerTest.cs" />
|
||||
<Compile Include="Recipes\RecipeHandlers\ModuleStepTest.cs" />
|
||||
<Compile Include="Recipes\RecipeHandlers\ThemeStepTest.cs" />
|
||||
@@ -336,6 +337,12 @@
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Recipes\Services\FoldersData\Sample2\Module.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Recipes\Services\FoldersData\Sample2\Recipes\duplicate-steps.recipe.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
@@ -94,7 +94,7 @@ Features:
|
||||
Enumerable.Empty<ShellParameter>());
|
||||
|
||||
var moduleStep = _container.Resolve<ModuleStep>();
|
||||
var recipeExecutionContext = new RecipeExecutionContext {RecipeStep = new RecipeStep( recipeName: "Test", name: "Module", step: new XElement("SuperWiki")) };
|
||||
var recipeExecutionContext = new RecipeExecutionContext {RecipeStep = new RecipeStep(id: "1", recipeName: "Test", name: "Module", step: new XElement("SuperWiki")) };
|
||||
recipeExecutionContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Module.SuperWiki"));
|
||||
recipeExecutionContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
|
||||
|
||||
@@ -120,7 +120,7 @@ Features:
|
||||
");
|
||||
|
||||
var moduleStep = _container.Resolve<ModuleStep>();
|
||||
var recipeContext = new RecipeContext { RecipeStep = new RecipeStep(recipeName: "Test", name: "Module", step: new XElement("SuperWiki")) };
|
||||
var recipeContext = new RecipeContext { RecipeStep = new RecipeStep(id: "1", recipeName: "Test", name: "Module", step: new XElement("SuperWiki")) };
|
||||
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = recipeContext.RecipeStep };
|
||||
recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
|
||||
|
||||
@@ -145,7 +145,7 @@ Features:
|
||||
});
|
||||
|
||||
var moduleStep = _container.Resolve<ModuleStep>();
|
||||
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = new RecipeStep(recipeName: "Test", name: "Module", step: new XElement("SuperWiki")) };
|
||||
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = new RecipeStep(id: "1", recipeName: "Test", name: "Module", step: new XElement("SuperWiki")) };
|
||||
|
||||
recipeExecutionContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Module.SuperWiki"));
|
||||
recipeExecutionContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
|
||||
|
@@ -25,7 +25,7 @@ namespace Orchard.Tests.Modules.Recipes.RecipeHandlers {
|
||||
var fakeRecipeStep = _container.Resolve<StubRecipeExecutionStep>();
|
||||
|
||||
var context = new RecipeContext {
|
||||
RecipeStep = new RecipeStep (recipeName: "FakeRecipe", name: "FakeRecipeStep", step: new XElement("FakeRecipeStep")),
|
||||
RecipeStep = new RecipeStep (id: "1", recipeName: "FakeRecipe", name: "FakeRecipeStep", step: new XElement("FakeRecipeStep")),
|
||||
ExecutionId = "12345"
|
||||
};
|
||||
|
||||
|
@@ -0,0 +1,29 @@
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Recipes.Services;
|
||||
|
||||
namespace Orchard.Tests.Modules.Recipes.RecipeHandlers {
|
||||
[TestFixture]
|
||||
public class RecipeParserTest {
|
||||
protected IContainer _container;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterType<RecipeParser>().As<IRecipeParser>();
|
||||
|
||||
_container = builder.Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingRecipeYieldsUniqueIdsForSteps() {
|
||||
var recipeText = @"<Orchard><Foo /><Bar /><Baz /></Orchard>";
|
||||
var recipeParser = _container.Resolve<IRecipeParser>();
|
||||
var recipe = recipeParser.ParseRecipe(recipeText);
|
||||
|
||||
// Assert that each step has a unique ID.
|
||||
Assert.IsTrue(recipe.RecipeSteps.GroupBy(x => x.Id).All(y => y.Count() == 1));
|
||||
}
|
||||
}
|
||||
}
|
@@ -100,7 +100,7 @@ Features:
|
||||
Enumerable.Empty<ShellParameter>());
|
||||
|
||||
var themeStep = _container.Resolve<ThemeStep>();
|
||||
var recipeExecutionContext = new RecipeExecutionContext {RecipeStep = new RecipeStep (recipeName: "Test", name: "Theme", step: new XElement("SuperWiki")) };
|
||||
var recipeExecutionContext = new RecipeExecutionContext {RecipeStep = new RecipeStep (id: "1", recipeName: "Test", name: "Theme", step: new XElement("SuperWiki")) };
|
||||
|
||||
recipeExecutionContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Theme.SuperWiki"));
|
||||
recipeExecutionContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
|
||||
@@ -135,7 +135,7 @@ Features:
|
||||
");
|
||||
|
||||
var themeStep = _container.Resolve<ThemeStep>();
|
||||
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = new RecipeStep(recipeName: "Test", name: "Theme", step: new XElement("SuperWiki")) };
|
||||
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = new RecipeStep(id: "1", recipeName: "Test", name: "Theme", step: new XElement("SuperWiki")) };
|
||||
|
||||
recipeExecutionContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
|
||||
Assert.Throws(typeof (InvalidOperationException), () => themeStep.Execute(recipeExecutionContext));
|
||||
@@ -159,7 +159,7 @@ Features:
|
||||
});
|
||||
|
||||
var themeStep = _container.Resolve<ThemeStep>();
|
||||
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = new RecipeStep(recipeName: "Test", name: "Theme", step: new XElement("SuperWiki")) };
|
||||
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = new RecipeStep(id: "1", recipeName: "Test", name: "Theme", step: new XElement("SuperWiki")) };
|
||||
|
||||
recipeExecutionContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Theme.SuperWiki"));
|
||||
recipeExecutionContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
|
||||
|
@@ -0,0 +1,8 @@
|
||||
Name: Le plug-in français
|
||||
Author: Bertrand Le Roy
|
||||
Description:
|
||||
This plug-in replaces
|
||||
'the' with 'le'
|
||||
Version: 1.4.1
|
||||
Tags: plug-in, français, the, le
|
||||
homepage: http://weblogs.asp.net/bleroy
|
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<Orchard>
|
||||
<Recipe>
|
||||
<Name>Duplicate Steps</Name>
|
||||
</Recipe>
|
||||
|
||||
<Recipes />
|
||||
<Recipes />
|
||||
<Recipes />
|
||||
|
||||
</Orchard>
|
||||
|
@@ -1,61 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Autofac;
|
||||
using Moq;
|
||||
using NHibernate;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Caching;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Folders;
|
||||
using Orchard.Environment.Extensions.Loaders;
|
||||
using Orchard.FileSystems.AppData;
|
||||
using Orchard.FileSystems.WebSite;
|
||||
using Orchard.Recipes.Events;
|
||||
using Orchard.Recipes.Models;
|
||||
using Orchard.Recipes.Services;
|
||||
using Orchard.Services;
|
||||
using Orchard.Tests.Environment.Extensions;
|
||||
using Orchard.Tests.Stubs;
|
||||
using Orchard.Recipes.Events;
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
[TestFixture]
|
||||
public class RecipeManagerTests {
|
||||
private IContainer _container;
|
||||
public class RecipeManagerTests : DatabaseEnabledTestsBase {
|
||||
private IRecipeManager _recipeManager;
|
||||
private IRecipeHarvester _recipeHarvester;
|
||||
private IRecipeParser _recipeParser;
|
||||
private IExtensionFolders _folders;
|
||||
private ISessionFactory _sessionFactory;
|
||||
private ISession _session;
|
||||
|
||||
private const string DataPrefix = "Orchard.Tests.Modules.Recipes.Services.FoldersData.";
|
||||
private string _tempFolderName;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void InitFixture() {
|
||||
var databaseFileName = System.IO.Path.GetTempFileName();
|
||||
_sessionFactory = DataUtility.CreateSessionFactory(
|
||||
databaseFileName,
|
||||
typeof(ContentTypeRecord),
|
||||
typeof(ContentItemRecord),
|
||||
typeof(ContentItemVersionRecord),
|
||||
typeof(RecipeStepResultRecord));
|
||||
protected override IEnumerable<Type> DatabaseTypes {
|
||||
get { yield return typeof (RecipeStepResultRecord); }
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
public override void Register(ContainerBuilder builder) {
|
||||
_tempFolderName = Path.GetTempFileName();
|
||||
File.Delete(_tempFolderName);
|
||||
var assembly = GetType().Assembly;
|
||||
foreach (var name in assembly.GetManifestResourceNames()) {
|
||||
if (name.StartsWith(DataPrefix)) {
|
||||
foreach (var name in assembly.GetManifestResourceNames())
|
||||
{
|
||||
if (name.StartsWith(DataPrefix))
|
||||
{
|
||||
string text;
|
||||
using (var stream = assembly.GetManifestResourceStream(name)) {
|
||||
using (var stream = assembly.GetManifestResourceStream(name))
|
||||
{
|
||||
using (var reader = new StreamReader(stream))
|
||||
text = reader.ReadToEnd();
|
||||
|
||||
@@ -73,15 +64,16 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
var targetPath = Path.Combine(_tempFolderName, relativePath);
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
|
||||
using (var stream = new FileStream(targetPath, FileMode.Create)) {
|
||||
using (var writer = new StreamWriter(stream)) {
|
||||
using (var stream = new FileStream(targetPath, FileMode.Create))
|
||||
{
|
||||
using (var writer = new StreamWriter(stream))
|
||||
{
|
||||
writer.Write(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var builder = new ContainerBuilder();
|
||||
var harvester = new ExtensionHarvester(new StubCacheManager(), new StubWebSiteFolder(), new Mock<ICriticalErrorProvider>().Object);
|
||||
_folders = new ModuleFolders(new[] { _tempFolderName }, harvester);
|
||||
builder.RegisterType<RecipeManager>().As<IRecipeManager>();
|
||||
@@ -97,21 +89,23 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
builder.RegisterType<StubAsyncTokenProvider>().As<IAsyncTokenProvider>();
|
||||
builder.RegisterInstance(_folders).As<IExtensionFolders>();
|
||||
builder.RegisterInstance(new Mock<IRecipeExecuteEventHandler>().Object);
|
||||
builder.RegisterType<Environment.Extensions.ExtensionManagerTests.StubLoaders>().As<IExtensionLoader>();
|
||||
builder.RegisterType<ExtensionManagerTests.StubLoaders>().As<IExtensionLoader>();
|
||||
builder.RegisterType<RecipeParser>().As<IRecipeParser>();
|
||||
builder.RegisterType<StubWebSiteFolder>().As<IWebSiteFolder>();
|
||||
builder.RegisterType<CustomRecipeHandler>().As<IRecipeHandler>();
|
||||
builder.RegisterInstance(new StubRecipeStepResultRecordRepository()).As<IRepository<RecipeStepResultRecord>>();
|
||||
}
|
||||
|
||||
public override void Init() {
|
||||
base.Init();
|
||||
|
||||
_container = builder.Build();
|
||||
_recipeManager = _container.Resolve<IRecipeManager>();
|
||||
_recipeParser = _container.Resolve<IRecipeParser>();
|
||||
_recipeHarvester = _container.Resolve<IRecipeHarvester>();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Term() {
|
||||
public override void Cleanup() {
|
||||
Directory.Delete(_tempFolderName, true);
|
||||
base.Cleanup();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -168,6 +162,38 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
|
||||
Assert.That(CustomRecipeHandler.AttributeValue == "value1");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExecuteUpdatesStepResults()
|
||||
{
|
||||
var recipes = (List<Recipe>)_recipeHarvester.HarvestRecipes("Sample1");
|
||||
var sampleRecipe = recipes.First();
|
||||
var steps = sampleRecipe.RecipeSteps.ToArray();
|
||||
|
||||
_recipeManager.Execute(sampleRecipe);
|
||||
|
||||
var stepResultRepository = _container.Resolve<IRepository<RecipeStepResultRecord>>();
|
||||
var stepResults = stepResultRepository.Table.ToArray();
|
||||
|
||||
Assert.That(stepResults.Count(), Is.EqualTo(steps.Count()));
|
||||
Assert.IsTrue(stepResults.All(x => x.IsCompleted));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanExecuteSameStepMultipleTimes()
|
||||
{
|
||||
var recipes = (List<Recipe>)_recipeHarvester.HarvestRecipes("Sample2");
|
||||
var recipe = recipes.Single(x => x.Name == "Duplicate Steps");
|
||||
var steps = recipe.RecipeSteps.ToArray();
|
||||
|
||||
_recipeManager.Execute(recipe);
|
||||
|
||||
var stepResultRepository = _container.Resolve<IRepository<RecipeStepResultRecord>>();
|
||||
var stepResults = stepResultRepository.Table.ToArray();
|
||||
|
||||
Assert.That(stepResults.Count(), Is.EqualTo(steps.Count()));
|
||||
Assert.IsTrue(stepResults.All(x => x.IsCompleted));
|
||||
}
|
||||
}
|
||||
|
||||
public class StubStepQueue : IRecipeStepQueue {
|
||||
@@ -182,22 +208,6 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
}
|
||||
}
|
||||
|
||||
public class StubRecipeStepResultRecordRepository : IRepository<RecipeStepResultRecord> {
|
||||
private List<RecipeStepResultRecord> _records = new List<RecipeStepResultRecord>();
|
||||
public IQueryable<RecipeStepResultRecord> Table { get { return _records.AsQueryable(); } }
|
||||
public void Copy(RecipeStepResultRecord source, RecipeStepResultRecord target) { }
|
||||
public int Count(Expression<Func<RecipeStepResultRecord, bool>> predicate) { return _records.Count; }
|
||||
public void Create(RecipeStepResultRecord entity) { _records.Add(entity); }
|
||||
public void Delete(RecipeStepResultRecord entity) { _records.Remove(entity); }
|
||||
public IEnumerable<RecipeStepResultRecord> Fetch(Expression<Func<RecipeStepResultRecord, bool>> predicate) { throw new NotImplementedException(); }
|
||||
public IEnumerable<RecipeStepResultRecord> Fetch(Expression<Func<RecipeStepResultRecord, bool>> predicate, Action<Orderable<RecipeStepResultRecord>> order) { throw new NotImplementedException(); }
|
||||
public IEnumerable<RecipeStepResultRecord> Fetch(Expression<Func<RecipeStepResultRecord, bool>> predicate, Action<Orderable<RecipeStepResultRecord>> order, int skip, int count) { throw new NotImplementedException(); }
|
||||
public void Flush() { }
|
||||
public RecipeStepResultRecord Get(Expression<Func<RecipeStepResultRecord, bool>> predicate) { throw new NotImplementedException(); }
|
||||
public RecipeStepResultRecord Get(int id) { throw new NotImplementedException(); }
|
||||
public void Update(RecipeStepResultRecord entity) { }
|
||||
}
|
||||
|
||||
public class StubRecipeScheduler : IRecipeScheduler {
|
||||
private readonly IRecipeStepExecutor _recipeStepExecutor;
|
||||
|
||||
@@ -212,7 +222,7 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
|
||||
public class CustomRecipeHandler : IRecipeHandler {
|
||||
public static string AttributeValue;
|
||||
public string[] _handles = { "Module", "Theme", "Migration", "Custom1", "Custom2", "Command", "Metadata", "Feature", "Settings" };
|
||||
public string[] _handles = { "Module", "Theme", "Migration", "Custom1", "Custom2", "Command", "Metadata", "Feature", "Settings", "Recipes" };
|
||||
|
||||
public void ExecuteRecipeStep(RecipeContext recipeContext) {
|
||||
if (_handles.Contains(recipeContext.RecipeStep.Name)) {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
@@ -255,7 +256,8 @@ namespace Orchard.Packaging.Controllers {
|
||||
var recipe = new Recipe {
|
||||
Name = "Test",
|
||||
RecipeSteps = featureIds.Select(
|
||||
x => new RecipeStep(
|
||||
(i,x) => new RecipeStep(
|
||||
id: i.ToString(CultureInfo.InvariantCulture),
|
||||
recipeName: "Test",
|
||||
name: "Feature",
|
||||
step: new XElement("Feature", new XAttribute("enable", x))))
|
||||
|
@@ -7,6 +7,7 @@ namespace Orchard.Recipes {
|
||||
.Column<int>("Id", c => c.PrimaryKey().Identity())
|
||||
.Column<string>("ExecutionId", c => c.WithLength(128).NotNull())
|
||||
.Column<string>("RecipeName", c => c.WithLength(256))
|
||||
.Column<string>("StepId", c => c.WithLength(32).NotNull())
|
||||
.Column<string>("StepName", c => c.WithLength(256).NotNull())
|
||||
.Column<bool>("IsCompleted", c => c.NotNull())
|
||||
.Column<bool>("IsSuccessful", c => c.NotNull())
|
||||
|
@@ -3,6 +3,7 @@
|
||||
public virtual int Id { get; set; }
|
||||
public virtual string ExecutionId { get; set; }
|
||||
public virtual string RecipeName { get; set; }
|
||||
public virtual string StepId { get; set; }
|
||||
public virtual string StepName { get; set; }
|
||||
public virtual bool IsCompleted { get; set; }
|
||||
public virtual bool IsSuccessful { get; set; }
|
||||
|
@@ -65,6 +65,7 @@ namespace Orchard.Recipes.Providers.Executors {
|
||||
_recipeStepResultRecordRepository.Create(new RecipeStepResultRecord {
|
||||
ExecutionId = executionId,
|
||||
RecipeName = recipe.Name,
|
||||
StepId = recipeStep.Id,
|
||||
StepName = recipeStep.Name
|
||||
});
|
||||
}
|
||||
|
@@ -48,6 +48,7 @@ namespace Orchard.Recipes.Services {
|
||||
_recipeStepResultRecordRepository.Create(new RecipeStepResultRecord {
|
||||
ExecutionId = executionId,
|
||||
RecipeName = recipe.Name,
|
||||
StepId = recipeStep.Id,
|
||||
StepName = recipeStep.Name
|
||||
});
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Logging;
|
||||
@@ -11,6 +12,7 @@ namespace Orchard.Recipes.Services {
|
||||
public Recipe ParseRecipe(XDocument recipeDocument) {
|
||||
var recipe = new Recipe();
|
||||
var recipeSteps = new List<RecipeStep>();
|
||||
var stepId = 0;
|
||||
|
||||
foreach (var element in recipeDocument.Root.Elements()) {
|
||||
// Recipe metadata.
|
||||
@@ -52,7 +54,7 @@ namespace Orchard.Recipes.Services {
|
||||
}
|
||||
// Recipe step.
|
||||
else {
|
||||
var recipeStep = new RecipeStep(recipeName: recipe.Name, name: element.Name.LocalName, step: element );
|
||||
var recipeStep = new RecipeStep(id: (++stepId).ToString(CultureInfo.InvariantCulture), recipeName: recipe.Name, name: element.Name.LocalName, step: element );
|
||||
recipeSteps.Add(recipeStep);
|
||||
}
|
||||
}
|
||||
|
@@ -11,18 +11,18 @@ namespace Orchard.Recipes.Services {
|
||||
private readonly IRecipeStepQueue _recipeStepQueue;
|
||||
private readonly IEnumerable<IRecipeHandler> _recipeHandlers;
|
||||
private readonly IRecipeExecuteEventHandler _recipeExecuteEventHandler;
|
||||
private readonly IRepository<RecipeStepResultRecord> _recipeStepResultRecordRepository;
|
||||
private readonly IRepository<RecipeStepResultRecord> _recipeStepResultRepository;
|
||||
|
||||
public RecipeStepExecutor(
|
||||
IRecipeStepQueue recipeStepQueue,
|
||||
IEnumerable<IRecipeHandler> recipeHandlers,
|
||||
IRecipeExecuteEventHandler recipeExecuteEventHandler,
|
||||
IRepository<RecipeStepResultRecord> recipeStepResultRecordRepository) {
|
||||
IRepository<RecipeStepResultRecord> recipeStepResultRepository) {
|
||||
|
||||
_recipeStepQueue = recipeStepQueue;
|
||||
_recipeHandlers = recipeHandlers;
|
||||
_recipeExecuteEventHandler = recipeExecuteEventHandler;
|
||||
_recipeStepResultRecordRepository = recipeStepResultRecordRepository;
|
||||
_recipeStepResultRepository = recipeStepResultRepository;
|
||||
}
|
||||
|
||||
public bool ExecuteNextStep(string executionId) {
|
||||
@@ -44,11 +44,11 @@ namespace Orchard.Recipes.Services {
|
||||
recipeHandler.ExecuteRecipeStep(recipeContext);
|
||||
}
|
||||
|
||||
UpdateStepResultRecord(executionId, nextRecipeStep.RecipeName, nextRecipeStep.Name, isSuccessful: true);
|
||||
UpdateStepResultRecord(executionId, nextRecipeStep.RecipeName, nextRecipeStep.Id, nextRecipeStep.Name, isSuccessful: true);
|
||||
_recipeExecuteEventHandler.RecipeStepExecuted(executionId, recipeContext);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
UpdateStepResultRecord(executionId, nextRecipeStep.RecipeName, nextRecipeStep.Name, isSuccessful: false, errorMessage: ex.Message);
|
||||
UpdateStepResultRecord(executionId, nextRecipeStep.RecipeName, nextRecipeStep.Id, nextRecipeStep.Name, isSuccessful: false, errorMessage: ex.Message);
|
||||
Logger.Error(ex, "Recipe execution failed because the step '{0}' failed.", nextRecipeStep.Name);
|
||||
while (_recipeStepQueue.Dequeue(executionId) != null);
|
||||
var message = T("Recipe execution with ID {0} failed because the step '{1}' failed to execute. The following exception was thrown:\n{2}\nRefer to the error logs for more information.", executionId, nextRecipeStep.Name, ex.Message);
|
||||
@@ -65,10 +65,10 @@ namespace Orchard.Recipes.Services {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void UpdateStepResultRecord(string executionId, string recipeName, string stepName, bool isSuccessful, string errorMessage = null) {
|
||||
private void UpdateStepResultRecord(string executionId, string recipeName, string stepId, string stepName, bool isSuccessful, string errorMessage = null) {
|
||||
var query =
|
||||
from record in _recipeStepResultRecordRepository.Table
|
||||
where record.ExecutionId == executionId && record.StepName == stepName
|
||||
from record in _recipeStepResultRepository.Table
|
||||
where record.ExecutionId == executionId && record.StepId == stepId && record.StepName == stepName
|
||||
select record;
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(recipeName))
|
||||
@@ -80,7 +80,7 @@ namespace Orchard.Recipes.Services {
|
||||
stepResultRecord.IsSuccessful = isSuccessful;
|
||||
stepResultRecord.ErrorMessage = errorMessage;
|
||||
|
||||
_recipeStepResultRecordRepository.Update(stepResultRecord);
|
||||
_recipeStepResultRepository.Update(stepResultRecord);
|
||||
}
|
||||
}
|
||||
}
|
@@ -26,6 +26,7 @@ namespace Orchard.Recipes.Services {
|
||||
public void Enqueue(string executionId, RecipeStep step) {
|
||||
Logger.Information("Enqueuing recipe step '{0}'.", step.Name);
|
||||
var recipeStepElement = new XElement("RecipeStep");
|
||||
recipeStepElement.Attr("Id", step.Id);
|
||||
recipeStepElement.Attr("RecipeName", step.RecipeName);
|
||||
recipeStepElement.Add(new XElement("Name", step.Name));
|
||||
recipeStepElement.Add(step.Step);
|
||||
@@ -54,9 +55,10 @@ namespace Orchard.Recipes.Services {
|
||||
// string to xelement
|
||||
var stepElement = XElement.Parse(_appDataFolder.ReadFile(stepPath));
|
||||
var stepName = stepElement.Element("Name").Value;
|
||||
var stepId = stepElement.Attr("Id");
|
||||
var recipeName = stepElement.Attr("RecipeName");
|
||||
Logger.Information("Dequeuing recipe step '{0}'.", stepName);
|
||||
recipeStep = new RecipeStep(recipeName: recipeName, name: stepName, step: stepElement.Element(stepName));
|
||||
recipeStep = new RecipeStep(id: stepId, recipeName: recipeName, name: stepName, step: stepElement.Element(stepName));
|
||||
_appDataFolder.DeleteFile(stepPath);
|
||||
}
|
||||
|
||||
|
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace Orchard.Recipes.Models {
|
||||
public class RecipeStep {
|
||||
public RecipeStep(string recipeName, string name, XElement step) {
|
||||
public RecipeStep(string id, string recipeName, string name, XElement step) {
|
||||
Id = id;
|
||||
RecipeName = recipeName;
|
||||
Name = name;
|
||||
Step = step;
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public string RecipeName { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public XElement Step { get; private set; }
|
||||
|
Reference in New Issue
Block a user