From e8dd56786b8576f09208abcb74fe1186dc2284c5 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Fri, 22 Mar 2013 05:04:32 +0600 Subject: [PATCH] Fixes: #U4-1986 - data type cache is not refreshed in load balanced environments. --- src/Umbraco.Core/Cache/CacheKeys.cs | 2 + .../Cache/CacheRefresherEventHandler.cs | 31 +++++++++++++ .../Cache/DataTypeCacheRefresher.cs | 46 +++++++++++++++++++ src/Umbraco.Web/Cache/DistributedCache.cs | 1 + .../Cache/DistributedCacheExtensions.cs | 23 ++++++++++ src/Umbraco.Web/Cache/MemberCacheRefresher.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 + .../datatype/DataTypeDefinition.cs | 43 +++++------------ .../businesslogic/relation/RelationType.cs | 13 ------ 9 files changed, 116 insertions(+), 46 deletions(-) create mode 100644 src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs index 0adab2b896..7bb30ff8f1 100644 --- a/src/Umbraco.Core/Cache/CacheKeys.cs +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -35,5 +35,7 @@ namespace Umbraco.Core.Cache public const string StylesheetCacheKey = "UmbracoStylesheet"; public const string StylesheetPropertyCacheKey = "UmbracoStylesheetProperty"; + public const string DataTypeCacheKey = "UmbracoDataTypeDefinition"; + } } \ No newline at end of file diff --git a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs index 17d00ae99d..1f49f44cc9 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs @@ -22,6 +22,15 @@ namespace Umbraco.Web.Cache { protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { + + //Bind to data type events + //NOTE: we need to bind to legacy and new API events currently: http://issues.umbraco.org/issue/U4-1979 + + global::umbraco.cms.businesslogic.datatype.DataTypeDefinition.Deleting += DataTypeDefinitionDeleting; + global::umbraco.cms.businesslogic.datatype.DataTypeDefinition.Saving += DataTypeDefinitionSaving; + DataTypeService.Deleted += DataTypeServiceDeleted; + DataTypeService.Saved += DataTypeServiceSaved; + //Bind to stylesheet events //NOTE: we need to bind to legacy and new API events currently: http://issues.umbraco.org/issue/U4-1979 @@ -88,6 +97,28 @@ namespace Umbraco.Web.Cache MediaService.Trashing += MediaServiceTrashing; } + #region DataType event handlers + static void DataTypeServiceSaved(IDataTypeService sender, Core.Events.SaveEventArgs e) + { + e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshDataTypeCache(x.Id)); + } + + static void DataTypeServiceDeleted(IDataTypeService sender, Core.Events.DeleteEventArgs e) + { + e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveDataTypeCache(x.Id)); + } + + static void DataTypeDefinitionSaving(global::umbraco.cms.businesslogic.datatype.DataTypeDefinition sender, System.EventArgs e) + { + DistributedCache.Instance.RefreshDataTypeCache(sender.Id); + } + + static void DataTypeDefinitionDeleting(global::umbraco.cms.businesslogic.datatype.DataTypeDefinition sender, System.EventArgs e) + { + DistributedCache.Instance.RemoveDataTypeCache(sender.Id); + } + #endregion + #region Stylesheet and stylesheet property event handlers static void StylesheetPropertyAfterSave(global::umbraco.cms.businesslogic.web.StylesheetProperty sender, SaveEventArgs e) { diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs new file mode 100644 index 0000000000..d0fbec43bd --- /dev/null +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -0,0 +1,46 @@ +using System; +using Umbraco.Core; +using Umbraco.Core.Cache; + +namespace Umbraco.Web.Cache +{ + /// + /// A cache refresher to ensure member cache is updated when members change + /// + public sealed class DataTypeCacheRefresher : CacheRefresherBase + { + + protected override DataTypeCacheRefresher Instance + { + get { return this; } + } + + public override Guid UniqueIdentifier + { + get { return new Guid(DistributedCache.DataTypeCacheRefresherId); } + } + + public override string Name + { + get { return "Clears data type cache"; } + } + + public override void Refresh(int id) + { + ClearCache(id); + base.Refresh(id); + } + + public override void Remove(int id) + { + ClearCache(id); + base.Remove(id); + } + + private void ClearCache(int id) + { + ApplicationContext.Current.ApplicationCache. + ClearCacheByKeySearch(string.Format("{0}{1}", CacheKeys.DataTypeCacheKey, id)); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Cache/DistributedCache.cs b/src/Umbraco.Web/Cache/DistributedCache.cs index 00bc7c3969..29959e75e2 100644 --- a/src/Umbraco.Web/Cache/DistributedCache.cs +++ b/src/Umbraco.Web/Cache/DistributedCache.cs @@ -46,6 +46,7 @@ namespace Umbraco.Web.Cache public const string DomainCacheRefresherId = "11290A79-4B57-4C99-AD72-7748A3CF38AF"; public const string StylesheetCacheRefresherId = "E0633648-0DEB-44AE-9A48-75C3A55CB670"; public const string StylesheetPropertyCacheRefresherId = "2BC7A3A4-6EB1-4FBC-BAA3-C9E7B6D36D38"; + public const string DataTypeCacheRefresherId = "35B16C25-A17E-45D7-BC8F-EDAB1DCC28D2"; #endregion diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs index 36eb98a123..736c173c44 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs @@ -48,6 +48,29 @@ namespace Umbraco.Web.Cache #endregion + #region Data type cache + /// + /// Refreshes the cache amongst servers for a template + /// + /// + /// + public static void RefreshDataTypeCache(this DistributedCache dc, int dataTypeId) + { + dc.Refresh(new Guid(DistributedCache.DataTypeCacheRefresherId), dataTypeId); + } + + /// + /// Removes the cache amongst servers for a template + /// + /// + /// + public static void RemoveDataTypeCache(this DistributedCache dc, int dataTypeId) + { + dc.Remove(new Guid(DistributedCache.DataTypeCacheRefresherId), dataTypeId); + } + + #endregion + #region Page cache /// /// Refreshes the cache amongst servers for all pages diff --git a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs index efd795b8db..4780a9e502 100644 --- a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Cache public override string Name { - get { return "Clears Member Cache from umbraco.library"; } + get { return "Clears Member Cache"; } } public override void Refresh(int id) diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index e16c39efe7..2df353346f 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -264,6 +264,7 @@ + diff --git a/src/umbraco.cms/businesslogic/datatype/DataTypeDefinition.cs b/src/umbraco.cms/businesslogic/datatype/DataTypeDefinition.cs index e8699d2ef0..0e7c76d1eb 100644 --- a/src/umbraco.cms/businesslogic/datatype/DataTypeDefinition.cs +++ b/src/umbraco.cms/businesslogic/datatype/DataTypeDefinition.cs @@ -3,6 +3,7 @@ using System.Data; using System.Collections; using System.Linq; +using Umbraco.Core.Cache; using umbraco.DataLayer; using System.Xml; using umbraco.interfaces; @@ -101,7 +102,7 @@ namespace umbraco.cms.businesslogic.datatype SqlHelper.ExecuteNonQuery("delete from cmsDataType where nodeId=@nodeId", SqlHelper.CreateParameter("@nodeId", this.Id)); base.delete(); - cache.Cache.ClearCacheItem(string.Format("UmbracoDataTypeDefinition{0}", Id)); + OnDeleting(new EventArgs()); } [Obsolete("Use the standard delete() method instead")] @@ -118,22 +119,6 @@ namespace umbraco.cms.businesslogic.datatype OnSaving(EventArgs.Empty); } - /* - public SortedList PreValues { - get { - SortedList retVal = new SortedList(); - SqlDataReader dr = SqlHelper.ExecuteReader("select id, value from cmsDataTypePreValues where dataTypeNodeId = @nodeId order by sortOrder", SqlHelper.CreateParameter("@nodeId", this.Id)); - while (dr.Read()) - { - retVal.Add(dr.GetString("id"), dr.GetString("value")); - } - dr.Close(); - - return retVal; - } - } - */ - public XmlElement ToXml(XmlDocument xd) { XmlElement dt = xd.CreateElement("DataType"); @@ -171,12 +156,12 @@ namespace umbraco.cms.businesslogic.datatype ) { - BusinessLogic.User u = umbraco.BusinessLogic.User.GetCurrent(); + BusinessLogic.User u = BusinessLogic.User.GetCurrent(); if (u == null) u = BusinessLogic.User.GetUser(0); - cms.businesslogic.datatype.controls.Factory f = new umbraco.cms.businesslogic.datatype.controls.Factory(); + var f = new controls.Factory(); DataTypeDefinition dtd = MakeNew(u, _name, new Guid(_def)); @@ -309,23 +294,17 @@ namespace umbraco.cms.businesslogic.datatype public static DataTypeDefinition GetDataTypeDefinition(int id) { - if (System.Web.HttpRuntime.Cache[string.Format("UmbracoDataTypeDefinition{0}", id.ToString())] == null) - { - DataTypeDefinition dt = new DataTypeDefinition(id); - System.Web.HttpRuntime.Cache.Insert(string.Format("UmbracoDataTypeDefinition{0}", id.ToString()), dt); - } - return (DataTypeDefinition)System.Web.HttpRuntime.Cache[string.Format("UmbracoDataTypeDefinition{0}", id.ToString())]; + return ApplicationContext.Current.ApplicationCache.GetCacheItem( + string.Format("{0}{1}", CacheKeys.DataTypeCacheKey, id), + () => new DataTypeDefinition(id)); } [Obsolete("Use GetDataTypeDefinition(int id) instead", false)] public static DataTypeDefinition GetDataTypeDefinition(Guid id) { - if (System.Web.HttpRuntime.Cache[string.Format("UmbracoDataTypeDefinition{0}", id.ToString())] == null) - { - DataTypeDefinition dt = new DataTypeDefinition(id); - System.Web.HttpRuntime.Cache.Insert(string.Format("UmbracoDataTypeDefinition{0}", id.ToString()), dt); - } - return (DataTypeDefinition)System.Web.HttpRuntime.Cache[string.Format("UmbracoDataTypeDefinition{0}", id.ToString())]; + return ApplicationContext.Current.ApplicationCache.GetCacheItem( + string.Format("{0}{1}", CacheKeys.DataTypeCacheKey, id), + () => new DataTypeDefinition(id)); } #endregion @@ -355,7 +334,7 @@ namespace umbraco.cms.businesslogic.datatype public delegate void DeleteEventHandler(DataTypeDefinition sender, EventArgs e); /// - /// Occurs when a macro is saved. + /// Occurs when a data type is saved. /// public static event SaveEventHandler Saving; protected virtual void OnSaving(EventArgs e) diff --git a/src/umbraco.cms/businesslogic/relation/RelationType.cs b/src/umbraco.cms/businesslogic/relation/RelationType.cs index fcc7079fdb..43b297cbbb 100644 --- a/src/umbraco.cms/businesslogic/relation/RelationType.cs +++ b/src/umbraco.cms/businesslogic/relation/RelationType.cs @@ -166,18 +166,5 @@ namespace umbraco.cms.businesslogic.relation #endregion - /// - /// Occurs when [after delete]. - /// - public static event EventHandler AfterDelete; - /// - /// Raises the event. - /// - /// The instance containing the event data. - private void FireAfterDelete(DeleteEventArgs e) - { - if (AfterDelete != null) - AfterDelete(this, e); - } } } \ No newline at end of file