From 72c5853fb1cac98b9505028b0f708795367effb8 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 6 Mar 2014 18:25:38 +1100 Subject: [PATCH] Completes: U4-3937 Ensure media is indexed across all servers in LB environment with Distributed Cache calls for members --- src/Umbraco.Web.UI/config/trees.config | 15 +-- .../config/umbracoSettings.config | 4 +- .../Cache/CacheRefresherEventHandler.cs | 26 ++--- .../Cache/DistributedCacheExtensions.cs | 23 ++++ src/Umbraco.Web/Cache/MemberCacheRefresher.cs | 14 ++- src/Umbraco.Web/Search/ExamineEvents.cs | 101 ++++++++++++------ 6 files changed, 117 insertions(+), 66 deletions(-) diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index 78e9dfc0db..6834440077 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -1,25 +1,21 @@  - - - - - + + - @@ -28,24 +24,19 @@ - - + - - - - \ No newline at end of file diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index feb1c5e82f..2662dd0ef6 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -224,7 +224,7 @@ - + 0 @@ -233,7 +233,7 @@ - umb1.dev + localhost diff --git a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs index 6f8e708219..92751092a0 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs @@ -596,22 +596,22 @@ namespace Umbraco.Web.Cache #endregion #region Media event handlers - static void MediaServiceTrashing(IMediaService sender, Core.Events.MoveEventArgs e) + static void MediaServiceTrashing(IMediaService sender, MoveEventArgs e) { DistributedCache.Instance.RemoveMediaCache(false, e.Entity); } - static void MediaServiceMoving(IMediaService sender, Core.Events.MoveEventArgs e) + static void MediaServiceMoving(IMediaService sender, MoveEventArgs e) { DistributedCache.Instance.RefreshMediaCache(e.Entity); } - static void MediaServiceDeleting(IMediaService sender, Core.Events.DeleteEventArgs e) + static void MediaServiceDeleting(IMediaService sender, DeleteEventArgs e) { DistributedCache.Instance.RemoveMediaCache(true, e.DeletedEntities.ToArray()); } - static void MediaServiceSaved(IMediaService sender, Core.Events.SaveEventArgs e) + static void MediaServiceSaved(IMediaService sender, SaveEventArgs e) { DistributedCache.Instance.RefreshMediaCache(e.SavedEntities.ToArray()); } @@ -619,27 +619,21 @@ namespace Umbraco.Web.Cache #region Member event handlers - static void MemberServiceDeleted(IMemberService sender, Core.Events.DeleteEventArgs e) + static void MemberServiceDeleted(IMemberService sender, DeleteEventArgs e) { - foreach (var m in e.DeletedEntities.ToArray()) - { - DistributedCache.Instance.RemoveMemberCache(m.Id); - } + DistributedCache.Instance.RemoveMemberCache(e.DeletedEntities.ToArray()); } - static void MemberServiceSaved(IMemberService sender, Core.Events.SaveEventArgs e) + static void MemberServiceSaved(IMemberService sender, SaveEventArgs e) { - foreach (var m in e.SavedEntities.ToArray()) - { - DistributedCache.Instance.RefreshMemberCache(m.Id); - } + DistributedCache.Instance.RefreshMemberCache(e.SavedEntities.ToArray()); } #endregion #region Member group event handlers - static void MemberGroupService_Deleted(IMemberGroupService sender, Core.Events.DeleteEventArgs e) + static void MemberGroupService_Deleted(IMemberGroupService sender, DeleteEventArgs e) { foreach (var m in e.DeletedEntities.ToArray()) { @@ -647,7 +641,7 @@ namespace Umbraco.Web.Cache } } - static void MemberGroupService_Saved(IMemberGroupService sender, Core.Events.SaveEventArgs e) + static void MemberGroupService_Saved(IMemberGroupService sender, SaveEventArgs e) { foreach (var m in e.SavedEntities.ToArray()) { diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs index e218537ef2..5b3d5ca02f 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs @@ -256,11 +256,33 @@ namespace Umbraco.Web.Cache #endregion #region Member cache + + /// + /// Refreshes the cache among servers for a member + /// + /// + /// + public static void RefreshMemberCache(this DistributedCache dc, params IMember[] members) + { + dc.Refresh(new Guid(DistributedCache.MemberCacheRefresherId), x => x.Id, members); + } + + /// + /// Removes the cache among servers for a member + /// + /// + /// + public static void RemoveMemberCache(this DistributedCache dc, params IMember[] members) + { + dc.Remove(new Guid(DistributedCache.MemberCacheRefresherId), x => x.Id, members); + } + /// /// Refreshes the cache among servers for a member /// /// /// + [Obsolete("Use the RefreshMemberCache with strongly typed IMember objects instead")] public static void RefreshMemberCache(this DistributedCache dc, int memberId) { dc.Refresh(new Guid(DistributedCache.MemberCacheRefresherId), memberId); @@ -271,6 +293,7 @@ namespace Umbraco.Web.Cache /// /// /// + [Obsolete("Use the RemoveMemberCache with strongly typed IMember objects instead")] public static void RemoveMemberCache(this DistributedCache dc, int memberId) { dc.Remove(new Guid(DistributedCache.MemberCacheRefresherId), memberId); diff --git a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs index 2b740e826d..5267602402 100644 --- a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs @@ -14,7 +14,7 @@ namespace Umbraco.Web.Cache /// /// This is not intended to be used directly in your code and it should be sealed but due to legacy code we cannot seal it. /// - public class MemberCacheRefresher : CacheRefresherBase + public class MemberCacheRefresher : TypedCacheRefresherBase { protected override MemberCacheRefresher Instance @@ -44,6 +44,18 @@ namespace Umbraco.Web.Cache base.Remove(id); } + public override void Refresh(IMember instance) + { + ClearCache(instance.Id); + base.Remove(instance); + } + + public override void Remove(IMember instance) + { + ClearCache(instance.Id); + base.Remove(instance); + } + private void ClearCache(int id) { ApplicationContext.Current.ApplicationCache.ClearPartialViewCache(); diff --git a/src/Umbraco.Web/Search/ExamineEvents.cs b/src/Umbraco.Web/Search/ExamineEvents.cs index 0d4cb9cdeb..c04920e289 100644 --- a/src/Umbraco.Web/Search/ExamineEvents.cs +++ b/src/Umbraco.Web/Search/ExamineEvents.cs @@ -60,10 +60,8 @@ namespace Umbraco.Web.Search CacheRefresherBase.CacheUpdated += UnpublishedPageCacheRefresherCacheUpdated; CacheRefresherBase.CacheUpdated += PublishedPageCacheRefresherCacheUpdated; CacheRefresherBase.CacheUpdated += MediaCacheRefresherCacheUpdated; + CacheRefresherBase.CacheUpdated += MemberCacheRefresherCacheUpdated; - Member.AfterSave += MemberAfterSave; - Member.AfterDelete += MemberAfterDelete; - var contentIndexer = ExamineManager.Instance.IndexProviderCollection["InternalIndexer"] as UmbracoContentIndexer; if (contentIndexer != null) { @@ -76,11 +74,55 @@ namespace Umbraco.Web.Search } } - /// + [SecuritySafeCritical] + static void MemberCacheRefresherCacheUpdated(MemberCacheRefresher sender, CacheRefresherEventArgs e) + { + switch (e.MessageType) + { + case MessageType.RefreshById: + var c1 = ApplicationContext.Current.Services.MemberService.GetById((int)e.MessageObject); + if (c1 != null) + { + ReIndexForMember(c1); + } + break; + case MessageType.RemoveById: + + // This is triggered when the item is permanently deleted + + DeleteIndexForEntity((int)e.MessageObject, false); + break; + case MessageType.RefreshByInstance: + var c3 = e.MessageObject as IMember; + if (c3 != null) + { + ReIndexForMember(c3); + } + break; + case MessageType.RemoveByInstance: + + // This is triggered when the item is permanently deleted + + var c4 = e.MessageObject as IMember; + if (c4 != null) + { + DeleteIndexForEntity(c4.Id, false); + } + break; + case MessageType.RefreshAll: + case MessageType.RefreshByJson: + default: + //We don't support these, these message types will not fire for unpublished content + break; + } + } + + /// /// Handles index management for all media events - basically handling saving/copying/trashing/deleting /// /// /// + [SecuritySafeCritical] static void MediaCacheRefresherCacheUpdated(MediaCacheRefresher sender, CacheRefresherEventArgs e) { switch (e.MessageType) @@ -265,24 +307,13 @@ namespace Umbraco.Web.Search } [SecuritySafeCritical] - private static void MemberAfterSave(Member sender, SaveEventArgs e) + private static void ReIndexForMember(IMember member) { - //ensure that only the providers are flagged to listen execute - var xml = ExamineXmlExtensions.ToXElement(sender.ToXml(new System.Xml.XmlDocument(), false)); - var providers = ExamineManager.Instance.IndexProviderCollection.OfType() - .Where(x => x.EnableDefaultEventHandler); - ExamineManager.Instance.ReIndexNode(xml, IndexTypes.Member, providers); - } - - [SecuritySafeCritical] - private static void MemberAfterDelete(Member sender, DeleteEventArgs e) - { - var nodeId = sender.Id.ToString(); - - //ensure that only the providers are flagged to listen execute - ExamineManager.Instance.DeleteFromIndex(nodeId, - ExamineManager.Instance.IndexProviderCollection.OfType() - .Where(x => x.EnableDefaultEventHandler)); + ExamineManager.Instance.ReIndexNode( + member.ToXml(), IndexTypes.Member, + ExamineManager.Instance.IndexProviderCollection.OfType() + //ensure that only the providers are flagged to listen execute + .Where(x => x.EnableDefaultEventHandler)); } /// @@ -310,14 +341,14 @@ namespace Umbraco.Web.Search private static void ReIndexForMedia(IMedia sender, bool isMediaPublished) { ExamineManager.Instance.ReIndexNode( - sender.ToXml(), "media", + sender.ToXml(), IndexTypes.Media, ExamineManager.Instance.IndexProviderCollection.OfType() - //Index this item for all indexers if the media is not trashed, otherwise if the item is trashed - // then only index this for indexers supporting unpublished media + //Index this item for all indexers if the media is not trashed, otherwise if the item is trashed + // then only index this for indexers supporting unpublished media - .Where(x => isMediaPublished || (x.SupportUnpublishedContent)) - .Where(x => x.EnableDefaultEventHandler)); + .Where(x => isMediaPublished || (x.SupportUnpublishedContent)) + .Where(x => x.EnableDefaultEventHandler)); } /// @@ -351,17 +382,17 @@ namespace Umbraco.Web.Search /// [SecuritySafeCritical] private static void ReIndexForContent(IContent sender, bool isContentPublished) - { - ExamineManager.Instance.ReIndexNode( - sender.ToXml(), "content", - ExamineManager.Instance.IndexProviderCollection.OfType() + { + ExamineManager.Instance.ReIndexNode( + sender.ToXml(), IndexTypes.Content, + ExamineManager.Instance.IndexProviderCollection.OfType() - //Index this item for all indexers if the content is published, otherwise if the item is not published - // then only index this for indexers supporting unpublished content + //Index this item for all indexers if the content is published, otherwise if the item is not published + // then only index this for indexers supporting unpublished content - .Where(x => isContentPublished || (x.SupportUnpublishedContent)) - .Where(x => x.EnableDefaultEventHandler)); - } + .Where(x => isContentPublished || (x.SupportUnpublishedContent)) + .Where(x => x.EnableDefaultEventHandler)); + } /// /// Converts a content node to XDocument