From f6490a897a07984d30a51c5d7687d42196004bdf Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Fri, 22 Mar 2013 00:49:07 +0600 Subject: [PATCH] Fixes: #U4-1978 - Creates DomainCacheRefresher - domain cache is now refreshed across all servers --- src/Umbraco.Core/Cache/CacheKeys.cs | 2 + .../Cache/CacheRefresherEventHandler.cs | 22 ++++ src/Umbraco.Web/Cache/DistributedCache.cs | 3 +- .../Cache/DistributedCacheExtensions.cs | 21 ++++ src/Umbraco.Web/Cache/DomainCacheRefresher.cs | 39 +++++++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + src/umbraco.cms/businesslogic/web/Domain.cs | 105 ++++++++---------- 7 files changed, 133 insertions(+), 60 deletions(-) create mode 100644 src/Umbraco.Web/Cache/DomainCacheRefresher.cs diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs index e2ea37cee9..16acefd60a 100644 --- a/src/Umbraco.Core/Cache/CacheKeys.cs +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -28,5 +28,7 @@ namespace Umbraco.Core.Cache public const string LanguageCacheKey = "UmbracoLanguageCache"; + public const string DomainCacheKey = "UmbracoDomainList"; + } } \ No newline at end of file diff --git a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs index 4d6215bf10..9822a8768c 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs @@ -9,6 +9,7 @@ using umbraco.BusinessLogic; using umbraco.cms.businesslogic; using umbraco.cms.businesslogic.member; using System.Linq; +using umbraco.cms.businesslogic.web; using Macro = umbraco.cms.businesslogic.macro.Macro; using Template = umbraco.cms.businesslogic.template.Template; @@ -30,6 +31,12 @@ namespace Umbraco.Web.Cache content.AfterUpdateDocumentCache += ContentAfterUpdateDocumentCache; content.AfterClearDocumentCache += ContentAfterClearDocumentCache; + //Bind to domain events + + Domain.AfterSave += DomainAfterSave; + Domain.AfterDelete += DomainAfterDelete; + Domain.New += DomainNew; + //Bind to language events //NOTE: we need to bind to legacy and new API events currently: http://issues.umbraco.org/issue/U4-1979 @@ -77,6 +84,21 @@ namespace Umbraco.Web.Cache MediaService.Trashing += MediaServiceTrashing; } + static void DomainNew(Domain sender, NewEventArgs e) + { + DistributedCache.Instance.RefreshDomainCache(sender); + } + + static void DomainAfterDelete(Domain sender, DeleteEventArgs e) + { + DistributedCache.Instance.RemoveDomainCache(sender); + } + + static void DomainAfterSave(Domain sender, SaveEventArgs e) + { + DistributedCache.Instance.RefreshDomainCache(sender); + } + /// /// Fires when a langauge is deleted /// diff --git a/src/Umbraco.Web/Cache/DistributedCache.cs b/src/Umbraco.Web/Cache/DistributedCache.cs index a34ef5e48a..d81ce0b939 100644 --- a/src/Umbraco.Web/Cache/DistributedCache.cs +++ b/src/Umbraco.Web/Cache/DistributedCache.cs @@ -43,7 +43,8 @@ namespace Umbraco.Web.Cache public const string UserCacheRefresherId = "E057AF6D-2EE6-41F4-8045-3694010F0AA6"; public const string ContentTypeCacheRefresherId = "6902E22C-9C10-483C-91F3-66B7CAE9E2F5"; public const string LanguageCacheRefresherId = "3E0F95D8-0BE5-44B8-8394-2B8750B62654"; - + public const string DomainCacheRefresherId = "11290A79-4B57-4C99-AD72-7748A3CF38AF"; + #endregion private static readonly DistributedCache InstanceObject = new DistributedCache(); diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs index 85a66f814e..8be2f88a69 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs @@ -4,6 +4,7 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Models; using umbraco; +using umbraco.cms.businesslogic.web; namespace Umbraco.Web.Cache { @@ -278,6 +279,26 @@ namespace Umbraco.Web.Cache } #endregion + #region Domain Cache + + public static void RefreshDomainCache(this DistributedCache dc, Domain domain) + { + if (domain != null) + { + dc.Refresh(new Guid(DistributedCache.DomainCacheRefresherId), domain.Id); + } + } + + public static void RemoveDomainCache(this DistributedCache dc, Domain domain) + { + if (domain != null) + { + dc.Remove(new Guid(DistributedCache.DomainCacheRefresherId), domain.Id); + } + } + + #endregion + #region Language Cache public static void RefreshLanguageCache(this DistributedCache dc, ILanguage language) diff --git a/src/Umbraco.Web/Cache/DomainCacheRefresher.cs b/src/Umbraco.Web/Cache/DomainCacheRefresher.cs new file mode 100644 index 0000000000..b2a4a2920f --- /dev/null +++ b/src/Umbraco.Web/Cache/DomainCacheRefresher.cs @@ -0,0 +1,39 @@ +using System; +using Umbraco.Core; +using Umbraco.Core.Cache; + +namespace Umbraco.Web.Cache +{ + /// + /// A cache refresher to ensure language cache is refreshed when languages change + /// + public sealed class DomainCacheRefresher : CacheRefresherBase + { + protected override DomainCacheRefresher Instance + { + get { return this; } + } + + public override Guid UniqueIdentifier + { + get { return new Guid(DistributedCache.DomainCacheRefresherId); } + } + + public override string Name + { + get { return "Domain cache refresher"; } + } + + public override void Refresh(int id) + { + ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.DomainCacheKey); + base.Refresh(id); + } + + public override void Remove(int id) + { + ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.DomainCacheKey); + base.Remove(id); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index a59ec5c5c0..71f078f6c3 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -267,6 +267,7 @@ + diff --git a/src/umbraco.cms/businesslogic/web/Domain.cs b/src/umbraco.cms/businesslogic/web/Domain.cs index db59dc3d1e..83bbb850ac 100644 --- a/src/umbraco.cms/businesslogic/web/Domain.cs +++ b/src/umbraco.cms/businesslogic/web/Domain.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; using System.Data; using System.Linq; +using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using umbraco.BusinessLogic; using umbraco.BusinessLogic.Actions; @@ -40,7 +42,7 @@ namespace umbraco.cms.businesslogic.web public Domain(int Id) { - initDomain(Id); + InitDomain(Id); } public Domain(string DomainName) @@ -50,10 +52,10 @@ namespace umbraco.cms.businesslogic.web SqlHelper.CreateParameter("@DomainName", DomainName)); if (result == null || !(result is int)) throw new Exception(string.Format("Domain name '{0}' does not exists", DomainName)); - initDomain((int) result); + InitDomain((int) result); } - private void initDomain(int id) + private void InitDomain(int id) { using (IRecordsReader dr = SqlHelper.ExecuteReader( "select domainDefaultLanguage, domainRootStructureID, domainName from umbracoDomains where id = @ID", @@ -112,39 +114,30 @@ namespace umbraco.cms.businesslogic.web public void Delete() { - DeleteEventArgs e = new DeleteEventArgs(); + var e = new DeleteEventArgs(); FireBeforeDelete(e); - if (!e.Cancel) { + if (!e.Cancel) + { SqlHelper.ExecuteNonQuery(string.Format("delete from umbracoDomains where id = {0}", Id)); - InvalidateCache(); - FireAfterDelete(e); } } public void Save(){ - SaveEventArgs e = new SaveEventArgs(); + var e = new SaveEventArgs(); FireBeforeSave(e); - if (!e.Cancel) { - InvalidateCache(); - + if (!e.Cancel) + { //Add save method here at some point so this actually does something besides fire events... - FireAfterSave(e); } } #region Statics - private static void InvalidateCache() - { - Cache.ClearCacheItem("UmbracoDomainList"); - } - private static readonly object getDomainsSyncLock = new object(); - internal static List GetDomains() { return GetDomains(false); @@ -152,29 +145,29 @@ namespace umbraco.cms.businesslogic.web internal static List GetDomains(bool includeWildcards) { - var domains = Cache.GetCacheItem>("UmbracoDomainList", getDomainsSyncLock, TimeSpan.FromMinutes(30), - delegate - { - List result = new List(); - using(IRecordsReader dr = SqlHelper.ExecuteReader( - "select id, domainName from umbracoDomains")) - { - while(dr.Read()) - { - string domainName = dr.GetString("domainName"); - int domainId = dr.GetInt("id"); - - if (result.Find(delegate(Domain d) { return d.Name == domainName; }) == null) - result.Add(new Domain(domainId)); - else - { - LogHelper.Warn(string.Format("Domain already exists in list ({0})", domainName)); - } - - } - } - return result; - }); + var domains = ApplicationContext.Current.ApplicationCache.GetCacheItem( + CacheKeys.DomainCacheKey, + TimeSpan.FromMinutes(30), + () => + { + var result = new List(); + using (var dr = SqlHelper.ExecuteReader( + "select id, domainName from umbracoDomains")) + { + while (dr.Read()) + { + var domainName = dr.GetString("domainName"); + var domainId = dr.GetInt("id"); + if (result.Find(d => d.Name == domainName) == null) + result.Add(new Domain(domainId)); + else + { + LogHelper.Warn(string.Format("Domain already exists in list ({0})", domainName)); + } + } + } + return result; + }); if (!includeWildcards) domains = domains.Where(d => !d.IsWildcard).ToList(); @@ -208,26 +201,20 @@ namespace umbraco.cms.businesslogic.web { if (Exists(DomainName.ToLower())) throw new Exception("Domain " + DomainName + " already exists!"); - else - { - //need to check if the language exists first - if (Language.GetAllAsList().Where(x => x.id == LanguageId).SingleOrDefault() == null) - { - throw new ArgumentException("No language exists for the LanguageId specified"); - } - - SqlHelper.ExecuteNonQuery("insert into umbracoDomains (domainDefaultLanguage, domainRootStructureID, domainName) values (@domainDefaultLanguage, @domainRootStructureID, @domainName)", - SqlHelper.CreateParameter("@domainDefaultLanguage", LanguageId), - SqlHelper.CreateParameter("@domainRootStructureID", RootNodeId), - SqlHelper.CreateParameter("@domainName", DomainName.ToLower())); - - InvalidateCache(); - NewEventArgs e = new NewEventArgs(); - new Domain(DomainName).OnNew(e); - } - + //need to check if the language exists first + if (Language.GetAllAsList().SingleOrDefault(x => x.id == LanguageId) == null) + { + throw new ArgumentException("No language exists for the LanguageId specified"); + } + + SqlHelper.ExecuteNonQuery("insert into umbracoDomains (domainDefaultLanguage, domainRootStructureID, domainName) values (@domainDefaultLanguage, @domainRootStructureID, @domainName)", + SqlHelper.CreateParameter("@domainDefaultLanguage", LanguageId), + SqlHelper.CreateParameter("@domainRootStructureID", RootNodeId), + SqlHelper.CreateParameter("@domainName", DomainName.ToLower())); + var e = new NewEventArgs(); + new Domain(DomainName).OnNew(e); } #endregion