From ebf15b905280f7d542f89b528ba2a5b17e93f2b8 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 2 Jan 2019 15:24:05 +0100 Subject: [PATCH] Fix CacheRefresher and DistributedCache --- ...ests.cs => DistributedCacheBinderTests.cs} | 40 ++++- .../Integration/ContentEventsTests.cs | 12 +- .../Scoping/ScopedNuCacheTests.cs | 11 +- .../Scoping/ScopedRepositoryTests.cs | 19 +-- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 15 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 2 +- .../Cache/DistributedCacheBinder.cs | 85 +++++++++++ .../Cache/DistributedCacheBinderComponent.cs | 24 +++ ....cs => DistributedCacheBinder_Handlers.cs} | 138 +++++------------- .../Cache/IDistributedCacheBinder.cs | 34 +++++ src/Umbraco.Web/Services/SectionService.cs | 12 +- src/Umbraco.Web/Umbraco.Web.csproj | 5 +- 12 files changed, 253 insertions(+), 144 deletions(-) rename src/Umbraco.Tests/Cache/{CacheRefresherComponentTests.cs => DistributedCacheBinderTests.cs} (87%) create mode 100644 src/Umbraco.Web/Cache/DistributedCacheBinder.cs create mode 100644 src/Umbraco.Web/Cache/DistributedCacheBinderComponent.cs rename src/Umbraco.Web/Cache/{CacheRefresherComponent.cs => DistributedCacheBinder_Handlers.cs} (86%) create mode 100644 src/Umbraco.Web/Cache/IDistributedCacheBinder.cs diff --git a/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs similarity index 87% rename from src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs rename to src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs index 0616b4098f..3cc5e061a5 100644 --- a/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs @@ -1,21 +1,23 @@ using System; -using System.Collections.Generic; using System.Linq; +using System.Threading; +using Moq; using NUnit.Framework; using Umbraco.Core.Composing; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Web.Cache; +using Umbraco.Web.PublishedCache; +using Umbraco.Web.Routing; namespace Umbraco.Tests.Cache { [TestFixture] [UmbracoTest(WithApplication = true)] - public class CacheRefresherEventHandlerTests : UmbracoTestBase + public class DistributedCacheBinderTests : UmbracoTestBase { [Test] public void Can_Find_All_Event_Handlers() @@ -114,7 +116,7 @@ namespace Umbraco.Tests.Cache var ok = true; foreach (var definition in definitions) { - var found = CacheRefresherComponent.FindHandler(definition); + var found = DistributedCacheBinder.FindHandler(definition); if (found == null) { Console.WriteLine("Couldn't find method for " + definition.EventName + " on " + definition.Sender.GetType()); @@ -123,5 +125,35 @@ namespace Umbraco.Tests.Cache } Assert.IsTrue(ok, "see log for details"); } + + [Test] + public void CanHandleEvent() + { + // refreshers.HandleEvents wants a UmbracoContext + // which wants an HttpContext, which we build using a SimpleWorkerRequest + // which requires these to be non-null + var domain = Thread.GetDomain(); + if (domain.GetData(".appPath") == null) + domain.SetData(".appPath", ""); + if (domain.GetData(".appVPath") == null) + domain.SetData(".appVPath", ""); + + // refreshers.HandleEvents wants a UmbracoContext + // which wants these + Container.RegisterSingleton(_ => Mock.Of()); + Container.RegisterCollectionBuilder(); + + // create some event definitions + var definitions = new IEventDefinition[] + { + // works because that event definition maps to an empty handler + new EventDefinition>(null, Current.Services.ContentTypeService, new SaveEventArgs(Enumerable.Empty()), "Saved"), + + }; + + // just assert it does not throw + var refreshers = new DistributedCacheBinder(null, null); + refreshers.HandleEvents(definitions); + } } } diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index af188c6a09..2aee582acc 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -2,19 +2,17 @@ using System.Collections.Generic; using System.Linq; using LightInject; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Sync; -using Umbraco.Tests.Cache.DistributedCache; using Umbraco.Tests.Services; using Umbraco.Tests.TestHelpers.Entities; -using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing; using Umbraco.Web.Cache; using static Umbraco.Tests.Cache.DistributedCache.DistributedCacheTests; @@ -34,8 +32,8 @@ namespace Umbraco.Tests.Integration { base.SetUp(); - _h1 = new CacheRefresherComponent(true); - _h1.Initialize(new DistributedCache()); + _h1 = new DistributedCacheBinder(new DistributedCache(), Mock.Of()); + _h1.BindEvents(true); _events = new List(); @@ -76,7 +74,7 @@ namespace Umbraco.Tests.Integration { base.TearDown(); - _h1?.Unbind(); + _h1?.UnbindEvents(); // clear ALL events @@ -86,7 +84,7 @@ namespace Umbraco.Tests.Integration ContentCacheRefresher.CacheUpdated -= ContentCacheUpdated; } - private CacheRefresherComponent _h1; + private DistributedCacheBinder _h1; private IList _events; private int _msgCount; private IContentType _contentType; diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index cf3285cd7e..211bdc3cdb 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Repositories; @@ -36,7 +37,7 @@ namespace Umbraco.Tests.Scoping [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)] public class ScopedNuCacheTests : TestWithDatabaseBase { - private CacheRefresherComponent _cacheRefresher; + private DistributedCacheBinder _distributedCacheBinder; protected override void Compose() { @@ -56,8 +57,8 @@ namespace Umbraco.Tests.Scoping { base.TearDown(); - _cacheRefresher?.Unbind(); - _cacheRefresher = null; + _distributedCacheBinder?.UnbindEvents(); + _distributedCacheBinder = null; _onPublishedAssertAction = null; ContentService.Published -= OnPublishedAssert; @@ -129,8 +130,8 @@ namespace Umbraco.Tests.Scoping var umbracoContext = GetUmbracoContextNu("http://example.com/", setSingleton: true); // wire cache refresher - _cacheRefresher = new CacheRefresherComponent(true); - _cacheRefresher.Initialize(new DistributedCache()); + _distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(), Mock.Of()); + _distributedCacheBinder.BindEvents(true); // create document type, document var contentType = new ContentType(-1) { Alias = "CustomDocument", Name = "Custom Document" }; diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 48bbdb1e22..9ace5860e1 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -13,6 +13,7 @@ using Umbraco.Web.Cache; using LightInject; using Moq; using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Sync; namespace Umbraco.Tests.Scoping @@ -21,7 +22,7 @@ namespace Umbraco.Tests.Scoping [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true)] public class ScopedRepositoryTests : TestWithDatabaseBase { - private CacheRefresherComponent _cacheRefresher; + private DistributedCacheBinder _distributedCacheBinder; protected override void Compose() { @@ -52,8 +53,8 @@ namespace Umbraco.Tests.Scoping [TearDown] public void Teardown() { - _cacheRefresher?.Unbind(); - _cacheRefresher = null; + _distributedCacheBinder?.UnbindEvents(); + _distributedCacheBinder = null; } [TestCase(true)] @@ -76,8 +77,8 @@ namespace Umbraco.Tests.Scoping // get user again - else we'd modify the one that's in the cache user = service.GetUserById(user.Id); - _cacheRefresher = new CacheRefresherComponent(true); - _cacheRefresher.Initialize(new DistributedCache()); + _distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(), Mock.Of()); + _distributedCacheBinder.BindEvents(true); Assert.IsNull(scopeProvider.AmbientScope); using (var scope = scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped)) @@ -157,8 +158,8 @@ namespace Umbraco.Tests.Scoping Assert.AreEqual(lang.Id, globalCached.Id); Assert.AreEqual("fr-FR", globalCached.IsoCode); - _cacheRefresher = new CacheRefresherComponent(true); - _cacheRefresher.Initialize(new DistributedCache()); + _distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(), Mock.Of()); + _distributedCacheBinder.BindEvents(true); Assert.IsNull(scopeProvider.AmbientScope); using (var scope = scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped)) @@ -249,8 +250,8 @@ namespace Umbraco.Tests.Scoping Assert.AreEqual(item.Id, globalCached.Id); Assert.AreEqual("item-key", globalCached.ItemKey); - _cacheRefresher = new CacheRefresherComponent(true); - _cacheRefresher.Initialize(new DistributedCache()); + _distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(), Mock.Of()); + _distributedCacheBinder.BindEvents(true); Assert.IsNull(scopeProvider.AmbientScope); using (var scope = scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped)) diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 5f4e653735..1afbf5cb12 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -7,6 +7,7 @@ using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; @@ -23,7 +24,7 @@ namespace Umbraco.Tests.Scoping [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)] public class ScopedXmlTests : TestWithDatabaseBase { - private CacheRefresherComponent _cacheRefresher; + private DistributedCacheBinder _distributedCacheBinder; protected override void Compose() { @@ -42,8 +43,8 @@ namespace Umbraco.Tests.Scoping [TearDown] public void Teardown() { - _cacheRefresher?.Unbind(); - _cacheRefresher = null; + _distributedCacheBinder?.UnbindEvents(); + _distributedCacheBinder = null; _onPublishedAssertAction = null; ContentService.Published -= OnPublishedAssert; @@ -90,8 +91,8 @@ namespace Umbraco.Tests.Scoping var item = new Content("name", -1, contentType); // wire cache refresher - _cacheRefresher = new CacheRefresherComponent(true); - _cacheRefresher.Initialize(new DistributedCache()); + _distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(), Mock.Of()); + _distributedCacheBinder.BindEvents(true); // check xml in context = "before" var xml = XmlInContext; @@ -209,8 +210,8 @@ namespace Umbraco.Tests.Scoping Current.Services.ContentTypeService.Save(contentType); // wire cache refresher - _cacheRefresher = new CacheRefresherComponent(true); - _cacheRefresher.Initialize(new DistributedCache()); + _distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(), Mock.Of()); + _distributedCacheBinder.BindEvents(true); // check xml in context = "before" var xml = XmlInContext; diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 7d1753a6b2..d58cf2a5b0 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -111,7 +111,7 @@ - + diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinder.cs b/src/Umbraco.Web/Cache/DistributedCacheBinder.cs new file mode 100644 index 0000000000..f7171a840a --- /dev/null +++ b/src/Umbraco.Web/Cache/DistributedCacheBinder.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Umbraco.Core; +using Umbraco.Core.Events; +using Umbraco.Core.Logging; + +namespace Umbraco.Web.Cache +{ + /// + /// Default implementation. + /// + public partial class DistributedCacheBinder : IDistributedCacheBinder + { + private static readonly ConcurrentDictionary FoundHandlers = new ConcurrentDictionary(); + private readonly DistributedCache _distributedCache; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// + /// + public DistributedCacheBinder(DistributedCache distributedCache, ILogger logger) + { + _distributedCache = distributedCache; + _logger = logger; + } + + // internal for tests + internal static MethodInfo FindHandler(IEventDefinition eventDefinition) + { + var name = eventDefinition.Sender.GetType().Name + "_" + eventDefinition.EventName; + + return FoundHandlers.GetOrAdd(name, n => CandidateHandlers.Value.FirstOrDefault(x => x.Name == n)); + } + + private static readonly Lazy CandidateHandlers = new Lazy(() => + { + var underscore = new[] { '_' }; + + return typeof(DistributedCacheBinder) + .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Select(x => + { + if (x.Name.Contains("_") == false) return null; + + var parts = x.Name.Split(underscore, StringSplitOptions.RemoveEmptyEntries).Length; + if (parts != 2) return null; + + var parameters = x.GetParameters(); + if (parameters.Length != 2) return null; + if (typeof(EventArgs).IsAssignableFrom(parameters[1].ParameterType) == false) return null; + return x; + }) + .WhereNotNull() + .ToArray(); + }); + + /// + public void HandleEvents(IEnumerable events) + { + // ensure we run with an UmbracoContext, because this may run in a background task, + // yet developers may be using the 'current' UmbracoContext in the event handlers + using (UmbracoContext.EnsureContext()) + { + foreach (var e in events) + { + var handler = FindHandler(e); + if (handler == null) + { + // fixme - should this be fatal (ie, an exception)? + var name = e.Sender.GetType().Name + "_" + e.EventName; + _logger.Warn("Dropping event {EventName} because no corresponding handler was found.", name); + continue; + } + + handler.Invoke(this, new[] { e.Sender, e.Args }); + } + } + } + } +} diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinderComponent.cs b/src/Umbraco.Web/Cache/DistributedCacheBinderComponent.cs new file mode 100644 index 0000000000..57b013a97c --- /dev/null +++ b/src/Umbraco.Web/Cache/DistributedCacheBinderComponent.cs @@ -0,0 +1,24 @@ +using Umbraco.Core; +using Umbraco.Core.Components; +using Umbraco.Core.Composing; + +namespace Umbraco.Web.Cache +{ + /// + /// Installs listeners on service events in order to refresh our caches. + /// + [RuntimeLevel(MinLevel = RuntimeLevel.Run)] + [RequiredComponent(typeof(IUmbracoCoreComponent))] // runs before every other IUmbracoCoreComponent! + public class DistributedCacheBinderComponent : UmbracoComponentBase, IUmbracoCoreComponent + { + public override void Compose(Composition composition) + { + composition.Container.RegisterSingleton(); + } + + public void Initialize(IDistributedCacheBinder distributedCacheBinder) + { + distributedCacheBinder.BindEvents(); + } + } +} diff --git a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs similarity index 86% rename from src/Umbraco.Web/Cache/CacheRefresherComponent.cs rename to src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs index a020b0d76f..81b133b9ef 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs @@ -1,56 +1,50 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; -using System.IO; -using Umbraco.Core; +using System.Linq; using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; -using System.Linq; -using System.Reflection; -using System.Web; -using System.Web.Hosting; -using Umbraco.Core.Components; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services.Changes; using Umbraco.Core.Services.Implement; -using Umbraco.Web.Composing; -using Umbraco.Web.Security; using Umbraco.Web.Services; -using LightInject; -using ApplicationTree = Umbraco.Core.Models.ApplicationTree; namespace Umbraco.Web.Cache { /// - /// Installs listeners on service events in order to refresh our caches. + /// Default implementation. /// - [RuntimeLevel(MinLevel = RuntimeLevel.Run)] - [RequiredComponent(typeof(IUmbracoCoreComponent))] // runs before every other IUmbracoCoreComponent! - public class CacheRefresherComponent : UmbracoComponentBase, IUmbracoCoreComponent + public partial class DistributedCacheBinder { - private static readonly ConcurrentDictionary FoundHandlers = new ConcurrentDictionary(); - private DistributedCache _distributedCache; private List _unbinders; - public CacheRefresherComponent() - { } + private void Bind(Action binder, Action unbinder) + { + // bind now + binder(); - // for tests - public CacheRefresherComponent(bool supportUnbinding) + // and register unbinder for later, if needed + _unbinders?.Add(unbinder); + } + + /// + public void UnbindEvents() + { + if (_unbinders == null) + throw new NotSupportedException(); + foreach (var unbinder in _unbinders) + unbinder(); + _unbinders = null; + } + + /// + public void BindEvents(bool supportUnbinding = false) { if (supportUnbinding) _unbinders = new List(); - } - public void Initialize(DistributedCache distributedCache) - { - Current.Logger.Info("Initializing Umbraco internal event handlers for cache refreshing."); - - _distributedCache = distributedCache; + _logger.Info("Initializing Umbraco internal event handlers for cache refreshing."); // bind to application tree events Bind(() => ApplicationTreeService.Deleted += ApplicationTreeService_Deleted, @@ -170,74 +164,6 @@ namespace Umbraco.Web.Cache () => RelationService.DeletedRelationType -= RelationService_DeletedRelationType); } - #region Events binding and handling - - private void Bind(Action binder, Action unbinder) - { - // bind now - binder(); - - // and register unbinder for later, if needed - _unbinders?.Add(unbinder); - } - - // for tests - internal void Unbind() - { - if (_unbinders == null) - throw new NotSupportedException(); - foreach (var unbinder in _unbinders) - unbinder(); - _unbinders = null; - } - - internal static MethodInfo FindHandler(IEventDefinition eventDefinition) - { - var name = eventDefinition.Sender.GetType().Name + "_" + eventDefinition.EventName; - - return FoundHandlers.GetOrAdd(name, n => CandidateHandlers.Value.FirstOrDefault(x => x.Name == n)); - } - - private static readonly Lazy CandidateHandlers = new Lazy(() => - { - var underscore = new[] { '_' }; - - return typeof(CacheRefresherComponent) - .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - .Select(x => - { - if (x.Name.Contains("_") == false) return null; - - var parts = x.Name.Split(underscore, StringSplitOptions.RemoveEmptyEntries).Length; - if (parts != 2) return null; - - var parameters = x.GetParameters(); - if (parameters.Length != 2) return null; - if (typeof(EventArgs).IsAssignableFrom(parameters[1].ParameterType) == false) return null; - return x; - }) - .WhereNotNull() - .ToArray(); - }); - - internal static void HandleEvents(IEnumerable events) - { - // ensure we run with an UmbracoContext, because this may run in a background task, - // yet developers may be using the 'current' UmbracoContext in the event handlers - using (UmbracoContext.EnsureContext()) - { - foreach (var e in events) - { - var handler = FindHandler(e); - if (handler == null) continue; - - handler.Invoke(null, new[] { e.Sender, e.Args }); - } - } - } - - #endregion - #region PublicAccessService private void PublicAccessService_Saved(IPublicAccessService sender, SaveEventArgs e) @@ -264,7 +190,8 @@ namespace Umbraco.Web.Cache /// case then we need to clear all user permissions cache. /// private void ContentService_Copied(IContentService sender, CopyEventArgs e) - { } + { + } /// /// Handles cache refreshing for when content is saved (not published) @@ -276,7 +203,8 @@ namespace Umbraco.Web.Cache /// stay up-to-date for unpublished content. /// private void ContentService_Saved(IContentService sender, SaveEventArgs e) - { } + { + } private void ContentService_Changed(IContentService sender, TreeChange.EventArgs args) { @@ -324,12 +252,12 @@ namespace Umbraco.Web.Cache #region Application event handlers - private void SectionService_New(Section sender, EventArgs e) + private void SectionService_New(ISectionService sender, EventArgs e) { _distributedCache.RefreshAllApplicationCache(); } - private void SectionService_Deleted(Section sender, EventArgs e) + private void SectionService_Deleted(ISectionService sender, EventArgs e) { _distributedCache.RefreshAllApplicationCache(); } @@ -439,7 +367,8 @@ namespace Umbraco.Web.Cache #region UserService - static void UserService_UserGroupPermissionsAssigned(IUserService sender, SaveEventArgs e) + // fixme STATIC?? + private void UserService_UserGroupPermissionsAssigned(IUserService sender, SaveEventArgs e) { //TODO: Not sure if we need this yet depends if we start caching permissions //var groupIds = e.SavedEntities.Select(x => x.UserGroupId).Distinct(); @@ -568,6 +497,7 @@ namespace Umbraco.Web.Cache _distributedCache.RemoveMemberGroupCache(m.Id); } } + #endregion #region RelationType diff --git a/src/Umbraco.Web/Cache/IDistributedCacheBinder.cs b/src/Umbraco.Web/Cache/IDistributedCacheBinder.cs new file mode 100644 index 0000000000..e4237fea94 --- /dev/null +++ b/src/Umbraco.Web/Cache/IDistributedCacheBinder.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using Umbraco.Core.Events; +using Umbraco.Core.Services.Implement; + +namespace Umbraco.Web.Cache +{ + /// + /// Binds events to the distributed cache. + /// + /// + /// Use to bind actual events, eg , to + /// the distributed cache, so that the proper refresh operations are executed when these events trigger. + /// Use to handle events that have not actually triggered, but have + /// been queued, so that the proper refresh operations are also executed. + /// + public interface IDistributedCacheBinder + { + /// + /// Handles events from definitions. + /// + void HandleEvents(IEnumerable events); + + /// + /// Binds actual events to the distributed cache. + /// + /// A value indicating whether to support unbinding the events. + void BindEvents(bool enableUnbinding = false); + + /// + /// Unbinds bounded events. + /// + void UnbindEvents(); + } +} diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index ff8279a411..5d013d7e79 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -200,7 +200,7 @@ namespace Umbraco.Web.Services }, true); //raise event - OnNew(new Section(name, alias, sortOrder), new EventArgs()); + OnNew(this /*new Section(name, alias, sortOrder)*/, new EventArgs()); } } @@ -235,7 +235,7 @@ namespace Umbraco.Web.Services }, true); //raise event - OnDeleted(section, new EventArgs()); + OnDeleted(this, new EventArgs()); } } @@ -262,8 +262,8 @@ namespace Umbraco.Web.Services return tmp; } - internal static event TypedEventHandler Deleted; - private static void OnDeleted(Section app, EventArgs args) + internal static event TypedEventHandler Deleted; + private static void OnDeleted(ISectionService app, EventArgs args) { if (Deleted != null) { @@ -271,8 +271,8 @@ namespace Umbraco.Web.Services } } - internal static event TypedEventHandler New; - private static void OnNew(Section app, EventArgs args) + internal static event TypedEventHandler New; + private static void OnNew(ISectionService app, EventArgs args) { if (New != null) { diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 6089e68325..17c2a54d81 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -108,7 +108,10 @@ + + + @@ -652,7 +655,7 @@ - +