diff --git a/src/Orchard.Tests/Stubs/StubDistributedLock.cs b/src/Orchard.Tests/Stubs/StubDistributedLock.cs index 120fb0ca5..341bd3732 100644 --- a/src/Orchard.Tests/Stubs/StubDistributedLock.cs +++ b/src/Orchard.Tests/Stubs/StubDistributedLock.cs @@ -17,6 +17,7 @@ namespace Orchard.Tests.Stubs { public void Dispose() { IsDisposed = true; + IsAcquired = false; } } } diff --git a/src/Orchard.Tests/Tasks/DistributedLockServiceTests.cs b/src/Orchard.Tests/Tasks/DistributedLockServiceTests.cs index 85d0772ff..a559540c1 100644 --- a/src/Orchard.Tests/Tasks/DistributedLockServiceTests.cs +++ b/src/Orchard.Tests/Tasks/DistributedLockServiceTests.cs @@ -14,6 +14,7 @@ namespace Orchard.Tests.Tasks { private DistributedLockService _distributedLockService; protected override void Register(ContainerBuilder builder) { + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().AsSelf(); @@ -24,6 +25,7 @@ namespace Orchard.Tests.Tasks { _distributedLockService = container.Resolve(); } + [Test] public void AcquiringLockSucceeds() { IDistributedLock @lock; diff --git a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs index bf0688b20..ec675dac8 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs @@ -29,6 +29,7 @@ using Orchard.Mvc.ViewEngines.ThemeAwareness; using Orchard.Recipes.Services; using Orchard.Settings; using Orchard.Tasks; +using Orchard.Tasks.Locking; using Orchard.Themes; using Orchard.UI.Notify; using Orchard.UI.PageClass; diff --git a/src/Orchard/Data/Migration/AutomaticDataMigrations.cs b/src/Orchard/Data/Migration/AutomaticDataMigrations.cs index f592f30fc..70cb78408 100644 --- a/src/Orchard/Data/Migration/AutomaticDataMigrations.cs +++ b/src/Orchard/Data/Migration/AutomaticDataMigrations.cs @@ -3,6 +3,7 @@ using System.Linq; using Orchard.Environment; using Orchard.Environment.Features; using Orchard.Logging; +using Orchard.Tasks.Locking; namespace Orchard.Data.Migration { /// @@ -11,13 +12,16 @@ namespace Orchard.Data.Migration { public class AutomaticDataMigrations : IOrchardShellEvents { private readonly IDataMigrationManager _dataMigrationManager; private readonly IFeatureManager _featureManager; + private readonly IDistributedLockService _distributedLockService; public AutomaticDataMigrations( IDataMigrationManager dataMigrationManager, - IFeatureManager featureManager - ) { + IFeatureManager featureManager, + IDistributedLockService distributedLockService) { + _dataMigrationManager = dataMigrationManager; _featureManager = featureManager; + _distributedLockService = distributedLockService; Logger = NullLogger.Instance; } @@ -25,24 +29,28 @@ namespace Orchard.Data.Migration { public ILogger Logger { get; set; } public void Activated() { + IDistributedLock @lock; + if (_distributedLockService.TryAcquireLock(GetType().FullName, TimeSpan.FromMinutes(30), TimeSpan.FromMilliseconds(250), out @lock)) { + using (@lock) { + // Let's make sure that the basic set of features is enabled. If there are any that are not enabled, then let's enable them first. + var theseFeaturesShouldAlwaysBeActive = new[] { + "Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation", "Scheduling", "Settings", "Shapes", "Title" + }; - // Let's make sure that the basic set of features is enabled. If there are any that are not enabled, then let's enable them first. - var theseFeaturesShouldAlwaysBeActive = new[] { - "Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation", "Scheduling", "Settings", "Shapes", "Title" - }; + var enabledFeatures = _featureManager.GetEnabledFeatures().Select(f => f.Id).ToList(); + var featuresToEnable = theseFeaturesShouldAlwaysBeActive.Where(shouldBeActive => !enabledFeatures.Contains(shouldBeActive)).ToList(); + if (featuresToEnable.Any()) { + _featureManager.EnableFeatures(featuresToEnable, true); + } - var enabledFeatures = _featureManager.GetEnabledFeatures().Select(f => f.Id).ToList(); - var featuresToEnable = theseFeaturesShouldAlwaysBeActive.Where(shouldBeActive => !enabledFeatures.Contains(shouldBeActive)).ToList(); - if (featuresToEnable.Any()) { - _featureManager.EnableFeatures(featuresToEnable, true); - } - - foreach (var feature in _dataMigrationManager.GetFeaturesThatNeedUpdate()) { - try { - _dataMigrationManager.Update(feature); - } - catch (Exception e) { - Logger.Error("Could not run migrations automatically on " + feature, e); + foreach (var feature in _dataMigrationManager.GetFeaturesThatNeedUpdate()) { + try { + _dataMigrationManager.Update(feature); + } + catch (Exception e) { + Logger.Error("Could not run migrations automatically on " + feature, e); + } + } } } } diff --git a/src/Orchard/Tasks/Locking/DefaultLock.cs b/src/Orchard/Tasks/Locking/DefaultLock.cs index adbf1dd36..df4ec1e7a 100644 --- a/src/Orchard/Tasks/Locking/DefaultLock.cs +++ b/src/Orchard/Tasks/Locking/DefaultLock.cs @@ -1,14 +1,31 @@ using System; namespace Orchard.Tasks.Locking { + public class DefaultLock : IDistributedLock { + private readonly IStaticLockSemaphore _semaphore; + + public DefaultLock(IStaticLockSemaphore semaphore) { + _semaphore = semaphore; + } public bool TryAcquire(string name, TimeSpan maxLifetime) { - return true; + if (_semaphore.IsAcquired) + return false; + + return _semaphore.IsAcquired = true; } public void Dispose() { - // Noop. + _semaphore.IsAcquired = false; + } + + public interface IStaticLockSemaphore : ISingletonDependency { + bool IsAcquired { get; set; } + } + + public class StaticLockSemaphore : IStaticLockSemaphore { + public bool IsAcquired { get; set; } } } } \ No newline at end of file