From ec46d65bb4df9fca6aa48631e0dcd349d731c06a Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Tue, 12 Mar 2013 03:00:42 +0400 Subject: [PATCH] Streamlines how macro cache is handled --- src/Umbraco.Core/ApplicationContext.cs | 2 +- src/Umbraco.Core/Cache/CacheKeys.cs | 21 +++++ .../{Sync => Cache}/ICacheRefresher.cs | 2 +- src/Umbraco.Core/CacheHelper.cs | 4 +- .../Sync/DefaultServerMessenger.cs | 1 + src/Umbraco.Core/Umbraco.Core.csproj | 3 +- .../Cache/CacheRefresherEventHandler.cs | 4 +- .../Cache/DistributedCacheExtensions.cs | 40 +++++++++ src/Umbraco.Web/Cache/MacroCacheRefresher.cs | 32 ++++++- src/Umbraco.Web/Cache/MediaCacheRefresher.cs | 7 +- src/Umbraco.Web/Cache/MemberCacheRefresher.cs | 5 +- src/Umbraco.Web/Cache/PageCacheRefresher.cs | 1 + .../Cache/TemplateCacheRefresher.cs | 6 +- src/Umbraco.Web/Cache/UserCacheRefresher.cs | 5 +- src/Umbraco.Web/umbraco.presentation/macro.cs | 90 ++++--------------- .../umbraco/create/macroTasks.cs | 2 - .../Packages/installedPackage.aspx.cs | 4 +- src/umbraco.cms/businesslogic/macro/Macro.cs | 79 ++++++++-------- 18 files changed, 167 insertions(+), 141 deletions(-) create mode 100644 src/Umbraco.Core/Cache/CacheKeys.cs rename src/Umbraco.Core/{Sync => Cache}/ICacheRefresher.cs (92%) diff --git a/src/Umbraco.Core/ApplicationContext.cs b/src/Umbraco.Core/ApplicationContext.cs index db58fb7858..53d576f995 100644 --- a/src/Umbraco.Core/ApplicationContext.cs +++ b/src/Umbraco.Core/ApplicationContext.cs @@ -40,7 +40,7 @@ namespace Umbraco.Core { //create a new application cache from the HttpRuntime.Cache ApplicationCache = HttpRuntime.Cache == null - ? new CacheHelper(new Cache()) + ? new CacheHelper(new System.Web.Caching.Cache()) : new CacheHelper(HttpRuntime.Cache); } diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs new file mode 100644 index 0000000000..97599d12d0 --- /dev/null +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -0,0 +1,21 @@ +namespace Umbraco.Core.Cache +{ + + /// + /// Constants storing cache keys used in caching + /// + public static class CacheKeys + { + public const string GetMediaCacheKey = "GetMedia"; + + //NOTE: pretty sure this is never used anymore + internal const string MacroRuntimeCacheKey = "UmbracoRuntimeMacroCache"; + public const string UmbracoMacroCacheKey = "UmbracoMacroCache"; + + public const string GetMemberCacheKey = "GetMember"; + + public const string TemplateCacheKey = "template"; + + public const string UserCacheKey = "UmbracoUser"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Sync/ICacheRefresher.cs b/src/Umbraco.Core/Cache/ICacheRefresher.cs similarity index 92% rename from src/Umbraco.Core/Sync/ICacheRefresher.cs rename to src/Umbraco.Core/Cache/ICacheRefresher.cs index eeb93184f8..e50c11fa35 100644 --- a/src/Umbraco.Core/Sync/ICacheRefresher.cs +++ b/src/Umbraco.Core/Cache/ICacheRefresher.cs @@ -1,6 +1,6 @@ using umbraco.interfaces; -namespace Umbraco.Core.Sync +namespace Umbraco.Core.Cache { /// /// Strongly type cache refresher that is able to refresh cache of real instances of objects as well as IDs diff --git a/src/Umbraco.Core/CacheHelper.cs b/src/Umbraco.Core/CacheHelper.cs index 428c88d01c..8aaa5c772d 100644 --- a/src/Umbraco.Core/CacheHelper.cs +++ b/src/Umbraco.Core/CacheHelper.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core /// public class CacheHelper { - private readonly Cache _cache; + private readonly System.Web.Caching.Cache _cache; public CacheHelper(System.Web.Caching.Cache cache) { @@ -173,7 +173,7 @@ namespace Umbraco.Core { //we use Insert instead of add if for some crazy reason there is now a cache with the cache key in there, it will just overwrite it. _cache.Insert(cacheKey, result, cacheDependency, - timeout == null ? Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value), + timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value), TimeSpan.Zero, priority, refreshAction); } } diff --git a/src/Umbraco.Core/Sync/DefaultServerMessenger.cs b/src/Umbraco.Core/Sync/DefaultServerMessenger.cs index 61dc5e98a0..9176a94728 100644 --- a/src/Umbraco.Core/Sync/DefaultServerMessenger.cs +++ b/src/Umbraco.Core/Sync/DefaultServerMessenger.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Net; using System.Threading; using System.Web.Script.Serialization; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using umbraco.interfaces; diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 69ad1f60e6..d18045b8c7 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -108,6 +108,7 @@ + @@ -691,7 +692,7 @@ - + Component diff --git a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs index 9dfd262b6e..2d1eca1416 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs @@ -87,7 +87,7 @@ namespace Umbraco.Web.Cache /// static void MacroAfterDelete(Macro sender, DeleteEventArgs e) { - DistributedCache.Instance.RemoveMacroCache(sender.Id); + DistributedCache.Instance.RemoveMacroCache(sender); } /// @@ -97,7 +97,7 @@ namespace Umbraco.Web.Cache /// static void MacroAfterSave(Macro sender, SaveEventArgs e) { - DistributedCache.Instance.RefreshMacroCache(sender.Id); + DistributedCache.Instance.RefreshMacroCache(sender); } static void MediaServiceTrashing(IMediaService sender, Core.Events.MoveEventArgs e) diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs index 6f9fb9fafd..b25e53f142 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Models; +using umbraco; namespace Umbraco.Web.Cache { @@ -159,6 +160,19 @@ namespace Umbraco.Web.Cache dc.Refresh(new Guid(DistributedCache.MacroCacheRefresherId), macroId); } + /// + /// Refreshes the cache amongst servers for a macro item + /// + /// + /// + public static void RefreshMacroCache(this DistributedCache dc, global::umbraco.cms.businesslogic.macro.Macro macro) + { + if (macro != null) + { + dc.Refresh(new Guid(DistributedCache.MacroCacheRefresherId), macro1 => macro1.Id, macro); + } + } + /// /// Removes the cache amongst servers for a macro item /// @@ -168,5 +182,31 @@ namespace Umbraco.Web.Cache { dc.Remove(new Guid(DistributedCache.MacroCacheRefresherId), macroId); } + + /// + /// Removes the cache amongst servers for a macro item + /// + /// + /// + public static void RemoveMacroCache(this DistributedCache dc, macro macro) + { + if (macro != null && macro.Model != null) + { + dc.Remove(new Guid(DistributedCache.MacroCacheRefresherId), macro1 => macro1.Model.Id, macro); + } + } + + /// + /// Removes the cache amongst servers for a macro item + /// + /// + /// + public static void RemoveMacroCache(this DistributedCache dc, global::umbraco.cms.businesslogic.macro.Macro macro) + { + if (macro != null) + { + dc.Remove(new Guid(DistributedCache.MacroCacheRefresherId), macro1 => macro1.Id, macro); + } + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs index 2f5c53a6e9..d5136414d5 100644 --- a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs @@ -1,4 +1,6 @@ using System; +using Umbraco.Core; +using Umbraco.Core.Cache; using umbraco; using umbraco.interfaces; @@ -7,8 +9,13 @@ namespace Umbraco.Web.Cache /// /// Used to invalidate/refresh the cache for macros /// - public class MacroCacheRefresher : ICacheRefresher + public class MacroCacheRefresher : ICacheRefresher { + internal static string[] GetCacheKeys(string alias) + { + return new[] { CacheKeys.MacroRuntimeCacheKey + alias, CacheKeys.UmbracoMacroCacheKey + alias }; + } + public string Name { get @@ -35,13 +42,32 @@ namespace Umbraco.Web.Cache void ICacheRefresher.Refresh(int id) { - macro.GetMacro(id).removeFromCache(); + if (id <= 0) return; + var m = new macro(id); + Remove(m); } void ICacheRefresher.Remove(int id) { - macro.GetMacro(id).removeFromCache(); + if (id <= 0) return; + var m = new macro(id); + Remove(m); } + public void Refresh(macro instance) + { + Remove(instance); + } + + public void Remove(macro instance) + { + if (instance != null && instance.Model != null && instance.Model.Id > 0) + { + GetCacheKeys(instance.Model.Alias).ForEach( + alias => + ApplicationContext.Current.ApplicationCache.ClearCacheItem(alias)); + + } + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs index b5efa092fc..74d3e91837 100644 --- a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs @@ -1,13 +1,12 @@ using System; using Umbraco.Core; +using Umbraco.Core.Cache; using umbraco.interfaces; namespace Umbraco.Web.Cache { public class MediaCacheRefresher : ICacheRefresher { - const string getmediaCacheKey = "GetMedia"; - public Guid UniqueIdentifier { get { return new Guid(DistributedCache.MediaCacheRefresherId); } @@ -44,12 +43,12 @@ namespace Umbraco.Web.Cache foreach (var idPart in m.Path.Split(',')) { ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch( - string.Format("UL_{0}_{1}_True", getmediaCacheKey, idPart)); + string.Format("UL_{0}_{1}_True", CacheKeys.GetMediaCacheKey, idPart)); // Also clear calls that only query this specific item! if (idPart == m.Id.ToString()) ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch( - string.Format("UL_{0}_{1}", getmediaCacheKey, id)); + string.Format("UL_{0}_{1}", CacheKeys.GetMediaCacheKey, id)); } } diff --git a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs index ce044ac6a9..deb7c828fd 100644 --- a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs @@ -1,5 +1,6 @@ using System; using Umbraco.Core; +using Umbraco.Core.Cache; using umbraco.interfaces; namespace Umbraco.Web.Cache @@ -38,10 +39,8 @@ namespace Umbraco.Web.Cache private void ClearCache(int id) { - const string getmemberCacheKey = "GetMember"; - ApplicationContext.Current.ApplicationCache. - ClearCacheByKeySearch(string.Format("UL_{0}_{1}", getmemberCacheKey, id)); + ClearCacheByKeySearch(string.Format("UL_{0}_{1}", CacheKeys.GetMemberCacheKey, id)); } } diff --git a/src/Umbraco.Web/Cache/PageCacheRefresher.cs b/src/Umbraco.Web/Cache/PageCacheRefresher.cs index 4b578a1fe2..bf709757e1 100644 --- a/src/Umbraco.Web/Cache/PageCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/PageCacheRefresher.cs @@ -1,4 +1,5 @@ using System; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Sync; using umbraco; diff --git a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs index 99496e3a2f..7820293569 100644 --- a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs @@ -1,5 +1,6 @@ using System; using Umbraco.Core; +using Umbraco.Core.Cache; using umbraco; using umbraco.interfaces; @@ -7,8 +8,7 @@ namespace Umbraco.Web.Cache { public class TemplateCacheRefresher : ICacheRefresher { - private const string TemplateCacheKey = "template"; - + public string Name { get @@ -46,7 +46,7 @@ namespace Umbraco.Web.Cache private void RemoveFromCache(int id) { ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch( - string.Format("{0}{1}", TemplateCacheKey, id)); + string.Format("{0}{1}", CacheKeys.TemplateCacheKey, id)); } } diff --git a/src/Umbraco.Web/Cache/UserCacheRefresher.cs b/src/Umbraco.Web/Cache/UserCacheRefresher.cs index 112024195e..9b8f6ecb8c 100644 --- a/src/Umbraco.Web/Cache/UserCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserCacheRefresher.cs @@ -1,5 +1,6 @@ using System; using Umbraco.Core; +using Umbraco.Core.Cache; using umbraco.interfaces; namespace Umbraco.Web.Cache @@ -20,7 +21,7 @@ namespace Umbraco.Web.Cache public void RefreshAll() { - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch("UmbracoUser"); + ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(CacheKeys.UserCacheKey); } public void Refresh(int id) @@ -30,7 +31,7 @@ namespace Umbraco.Web.Cache public void Remove(int id) { - ApplicationContext.Current.ApplicationCache.ClearCacheItem(string.Format("UmbracoUser{0}", id.ToString())); + ApplicationContext.Current.ApplicationCache.ClearCacheItem(string.Format("{0}{1}", CacheKeys.UserCacheKey, id.ToString())); } public void Refresh(Guid id) diff --git a/src/Umbraco.Web/umbraco.presentation/macro.cs b/src/Umbraco.Web/umbraco.presentation/macro.cs index cb97423082..503a18f30a 100644 --- a/src/Umbraco.Web/umbraco.presentation/macro.cs +++ b/src/Umbraco.Web/umbraco.presentation/macro.cs @@ -20,6 +20,7 @@ using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Web; +using Umbraco.Web.Cache; using Umbraco.Web.Macros; using Umbraco.Web.Templates; using umbraco.BusinessLogic; @@ -50,9 +51,6 @@ namespace umbraco private readonly StringBuilder mContent = new StringBuilder(); private readonly Cache macroCache = HttpRuntime.Cache; - private static readonly object macroRuntimeCacheSyncLock = new object(); - private static readonly string macroRuntimeCacheKey = "UmbracoRuntimeMacroCache"; - private readonly string macrosAddedKey = "macrosAdded"; public IList Exceptions = new List(); @@ -141,78 +139,31 @@ namespace umbraco public macro(int id) { Macro m = Macro.GetById(id); - Model = new MacroModel(m); + if (m != null) + { + Model = new MacroModel(m); + } } public macro(string alias) { Macro m = Macro.GetByAlias(alias); - Model = new MacroModel(m); + if (m != null) + { + Model = new MacroModel(m); + } } public MacroModel Model { get; set; } public static macro GetMacro(string alias) { - // FlorisRobbemont: issue #27610 -> Presentation macro not supposed to be cached. return new macro(alias); - - //return cms.businesslogic.cache.Cache.GetCacheItem(GetCacheKey(alias), macroRuntimeCacheSyncLock, - // TimeSpan.FromMinutes(60), - // delegate - // { - // try - // { - // return new macro(alias); - // } - // catch - // { - // return null; - // } - // }); - - - - - } - - - - - - public static macro GetMacro(int id) - { - // FlorisRobbemont: issue #27610 -> Presentation macro not supposed to be cached. - - - - - - + { return new macro(id); - - //return cms.businesslogic.cache.Cache.GetCacheItem(GetCacheKey(string.Format("by_id_{0}", id)), macroRuntimeCacheSyncLock, - // TimeSpan.FromMinutes(60), - // delegate - // { - // try - // { - // return new macro(id); - // } - // catch - // { - // return null; - // } - // }); - - - - - - } #endregion @@ -241,22 +192,16 @@ namespace umbraco return Model.Name; } - private static string GetCacheKey(string alias) - { - return macroRuntimeCacheKey + alias; - } - /// /// Deletes macro definition from cache. /// /// True if succesfull, false if nothing has been removed - //TODO: Update implementation! + [Obsolete("Use DistributedCache.Instance.RemoveMacroCache instead, macro cache will automatically be cleared and shouldn't need to be manually cleared.")] public bool removeFromCache() { - if (Model.Id > 0) - { - cms.businesslogic.cache.Cache.ClearCacheItem(GetCacheKey(Model.Alias)); - } + DistributedCache.Instance.RemoveMacroCache(this); + + //this always returned false... hrm. oh well i guess we leave it like that return false; } @@ -921,12 +866,13 @@ namespace umbraco // would not be refreshed when the .config file is modified. An application // restart would be required. Better use the cache and add a dependency. - // SD: Not sure what is meant by the above statement? Having these in a static variable would be preferred! + // SD: The only reason the above statement might be true is because the xslt extension .config file is not a + // real config file!! if it was, we wouldn't have this issue. Having these in a static variable would be preferred! // If you modify a config file, the app restarts and thus all static variables are reset. // Having this stuff in cache just adds to the gigantic amount of cache data and will cause more cache turnover to happen. - return cms.businesslogic.cache.Cache.GetCacheItem( - _xsltExtensionsCacheKey, _xsltExtensionsSyncLock, + return ApplicationContext.Current.ApplicationCache.GetCacheItem( + _xsltExtensionsCacheKey, CacheItemPriority.NotRemovable, // NH 4.7.1, Changing to NotRemovable null, // no refresh action _xsltExtensionsDependency(), // depends on the .config file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/macroTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/macroTasks.cs index be15eaea5f..eb19839f4f 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/macroTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/macroTasks.cs @@ -61,8 +61,6 @@ namespace umbraco public bool Delete() { - // Clear cache! - macro.GetMacro(ParentID).removeFromCache(); new cms.businesslogic.macro.Macro(ParentID).Delete(); return true; } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs index 74dca38e7e..5bd3dff108 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs @@ -437,9 +437,7 @@ namespace umbraco.presentation.developer.packages { Macro s = new Macro(nId); if (s != null && !String.IsNullOrEmpty(s.Name)) - { - // remove from cache - runtimeMacro.GetMacro(s.Id).removeFromCache(); + { s.Delete(); } diff --git a/src/umbraco.cms/businesslogic/macro/Macro.cs b/src/umbraco.cms/businesslogic/macro/Macro.cs index a69aff9cc5..4e265a5bf4 100644 --- a/src/umbraco.cms/businesslogic/macro/Macro.cs +++ b/src/umbraco.cms/businesslogic/macro/Macro.cs @@ -5,6 +5,8 @@ using System.Text; using System.Text.RegularExpressions; using System.Xml; using System.Runtime.CompilerServices; +using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.IO; using Umbraco.Core.Logging; using umbraco.cms.businesslogic.cache; @@ -28,7 +30,7 @@ namespace umbraco.cms.businesslogic.macro public class Macro { private static readonly object macroCacheSyncLock = new object(); - private static readonly string umbracoMacroCacheKey = "UmbracoMacroCache"; + //private static readonly string umbracoMacroCacheKey = "UmbracoMacroCache"; int _id; bool _useInEditor; @@ -279,11 +281,9 @@ namespace umbraco.cms.businesslogic.macro public virtual void Save() { //event - SaveEventArgs e = new SaveEventArgs(); + var e = new SaveEventArgs(); FireBeforeSave(e); - InvalidateCache(); - if (!e.Cancel) { FireAfterSave(e); } @@ -496,41 +496,42 @@ namespace umbraco.cms.businesslogic.macro /// /// Static contructor for retrieving a macro given an alias /// - /// The alias of the macro + /// The alias of the macro /// If the macro with the given alias exists, it returns the macro, else null - public static Macro GetByAlias(string alias) - { - return Cache.GetCacheItem(GetCacheKey(alias), macroCacheSyncLock, - TimeSpan.FromMinutes(30), - delegate - { - try - { - return new Macro(alias); - } - catch - { - return null; - } - }); - } + { + return ApplicationContext.Current.ApplicationCache.GetCacheItem( + GetCacheKey(alias), + TimeSpan.FromMinutes(30), + delegate + { + try + { + return new Macro(alias); + } + catch + { + return null; + } + }); + } public static Macro GetById(int id) { - return Cache.GetCacheItem(GetCacheKey(string.Format("macro_via_id_{0}", id)), macroCacheSyncLock, - TimeSpan.FromMinutes(30), - delegate - { - try - { - return new Macro(id); - } - catch - { - return null; - } - }); + return ApplicationContext.Current.ApplicationCache.GetCacheItem( + GetCacheKey(string.Format("macro_via_id_{0}", id)), + TimeSpan.FromMinutes(30), + delegate + { + try + { + return new Macro(id); + } + catch + { + return null; + } + }); } public static MacroTypes FindMacroType(string xslt, string scriptFile, string scriptType, string scriptAssembly) @@ -578,18 +579,12 @@ namespace umbraco.cms.businesslogic.macro } #region Macro Refactor - - private void InvalidateCache() - { - Cache.ClearCacheItem(GetCacheKey(this.Alias)); - } - + private static string GetCacheKey(string alias) { - return umbracoMacroCacheKey + alias; + return CacheKeys.UmbracoMacroCacheKey + alias; } - #endregion