diff --git a/src/Umbraco.Core/Cache/IsolatedRuntimeCache.cs b/src/Umbraco.Core/Cache/IsolatedRuntimeCache.cs index 103f90345d..da20f7eb73 100644 --- a/src/Umbraco.Core/Cache/IsolatedRuntimeCache.cs +++ b/src/Umbraco.Core/Cache/IsolatedRuntimeCache.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Cache /// public class IsolatedRuntimeCache { - private readonly Func _cacheFactory; + internal Func CacheFactory { get; set; } /// /// Constructor that allows specifying a factory for the type of runtime isolated cache to create @@ -20,7 +20,7 @@ namespace Umbraco.Core.Cache /// public IsolatedRuntimeCache(Func cacheFactory) { - _cacheFactory = cacheFactory; + CacheFactory = cacheFactory; } private readonly ConcurrentDictionary _isolatedCache = new ConcurrentDictionary(); @@ -32,7 +32,7 @@ namespace Umbraco.Core.Cache /// public IRuntimeCacheProvider GetOrCreateCache() { - return _isolatedCache.GetOrAdd(typeof(T), type => _cacheFactory(type)); + return _isolatedCache.GetOrAdd(typeof(T), type => CacheFactory(type)); } /// @@ -41,7 +41,7 @@ namespace Umbraco.Core.Cache /// public IRuntimeCacheProvider GetOrCreateCache(Type type) { - return _isolatedCache.GetOrAdd(type, t => _cacheFactory(t)); + return _isolatedCache.GetOrAdd(type, t => CacheFactory(t)); } /// diff --git a/src/Umbraco.Core/CacheHelper.cs b/src/Umbraco.Core/CacheHelper.cs index 303cf234fd..4b009e5f86 100644 --- a/src/Umbraco.Core/CacheHelper.cs +++ b/src/Umbraco.Core/CacheHelper.cs @@ -18,12 +18,8 @@ namespace Umbraco.Core /// public class CacheHelper { - private readonly IsolatedRuntimeCache _isolatedCacheManager; - private readonly ICacheProvider _requestCache; private static readonly ICacheProvider NullRequestCache = new NullCacheProvider(); - private readonly ICacheProvider _staticCache; private static readonly ICacheProvider NullStaticCache = new NullCacheProvider(); - private readonly IRuntimeCacheProvider _runtimeCache; private static readonly IRuntimeCacheProvider NullRuntimeCache = new NullCacheProvider(); /// @@ -90,45 +86,33 @@ namespace Umbraco.Core if (staticCacheProvider == null) throw new ArgumentNullException("staticCacheProvider"); if (requestCacheProvider == null) throw new ArgumentNullException("requestCacheProvider"); if (isolatedCacheManager == null) throw new ArgumentNullException("isolatedCacheManager"); - _runtimeCache = httpCacheProvider; - _staticCache = staticCacheProvider; - _requestCache = requestCacheProvider; - _isolatedCacheManager = isolatedCacheManager; + RuntimeCache = httpCacheProvider; + StaticCache = staticCacheProvider; + RequestCache = requestCacheProvider; + IsolatedRuntimeCache = isolatedCacheManager; } /// /// Returns the current Request cache /// - public ICacheProvider RequestCache - { - get { return _requestCache; } - } + public ICacheProvider RequestCache { get; internal set; } /// /// Returns the current Runtime cache /// - public ICacheProvider StaticCache - { - get { return _staticCache; } - } + public ICacheProvider StaticCache { get; internal set; } /// /// Returns the current Runtime cache /// - public IRuntimeCacheProvider RuntimeCache - { - get { return _runtimeCache; } - } + public IRuntimeCacheProvider RuntimeCache { get; internal set; } /// /// Returns the current Isolated Runtime cache manager /// - public IsolatedRuntimeCache IsolatedRuntimeCache - { - get { return _isolatedCacheManager; } - } - - #region Legacy Runtime/Http Cache accessors + public IsolatedRuntimeCache IsolatedRuntimeCache { get; internal set; } + + #region Legacy Runtime/Http Cache accessors /// /// Clears the item in umbraco's runtime cache @@ -137,8 +121,8 @@ namespace Umbraco.Core [EditorBrowsable(EditorBrowsableState.Never)] public void ClearAllCache() { - _runtimeCache.ClearAllCache(); - _isolatedCacheManager.ClearAllCaches(); + RuntimeCache.ClearAllCache(); + IsolatedRuntimeCache.ClearAllCaches(); } /// @@ -149,7 +133,7 @@ namespace Umbraco.Core [EditorBrowsable(EditorBrowsableState.Never)] public void ClearCacheItem(string key) { - _runtimeCache.ClearCacheItem(key); + RuntimeCache.ClearCacheItem(key); } @@ -161,7 +145,7 @@ namespace Umbraco.Core [Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")] public void ClearCacheObjectTypes(string typeName) { - _runtimeCache.ClearCacheObjectTypes(typeName); + RuntimeCache.ClearCacheObjectTypes(typeName); } /// @@ -171,7 +155,7 @@ namespace Umbraco.Core [EditorBrowsable(EditorBrowsableState.Never)] public void ClearCacheObjectTypes() { - _runtimeCache.ClearCacheObjectTypes(); + RuntimeCache.ClearCacheObjectTypes(); } /// @@ -182,7 +166,7 @@ namespace Umbraco.Core [EditorBrowsable(EditorBrowsableState.Never)] public void ClearCacheByKeySearch(string keyStartsWith) { - _runtimeCache.ClearCacheByKeySearch(keyStartsWith); + RuntimeCache.ClearCacheByKeySearch(keyStartsWith); } /// @@ -193,14 +177,14 @@ namespace Umbraco.Core [EditorBrowsable(EditorBrowsableState.Never)] public void ClearCacheByKeyExpression(string regexString) { - _runtimeCache.ClearCacheByKeyExpression(regexString); + RuntimeCache.ClearCacheByKeyExpression(regexString); } [Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")] [EditorBrowsable(EditorBrowsableState.Never)] public IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) { - return _runtimeCache.GetCacheItemsByKeySearch(keyStartsWith); + return RuntimeCache.GetCacheItemsByKeySearch(keyStartsWith); } /// @@ -213,7 +197,7 @@ namespace Umbraco.Core [EditorBrowsable(EditorBrowsableState.Never)] public TT GetCacheItem(string cacheKey) { - return _runtimeCache.GetCacheItem(cacheKey); + return RuntimeCache.GetCacheItem(cacheKey); } /// @@ -227,7 +211,7 @@ namespace Umbraco.Core [EditorBrowsable(EditorBrowsableState.Never)] public TT GetCacheItem(string cacheKey, Func getCacheItem) { - return _runtimeCache.GetCacheItem(cacheKey, getCacheItem); + return RuntimeCache.GetCacheItem(cacheKey, getCacheItem); } @@ -244,7 +228,7 @@ namespace Umbraco.Core public TT GetCacheItem(string cacheKey, TimeSpan timeout, Func getCacheItem) { - return _runtimeCache.GetCacheItem(cacheKey, getCacheItem, timeout); + return RuntimeCache.GetCacheItem(cacheKey, getCacheItem, timeout); } @@ -263,7 +247,7 @@ namespace Umbraco.Core CacheItemRemovedCallback refreshAction, TimeSpan timeout, Func getCacheItem) { - return _runtimeCache.GetCacheItem(cacheKey, getCacheItem, timeout, removedCallback: refreshAction); + return RuntimeCache.GetCacheItem(cacheKey, getCacheItem, timeout, removedCallback: refreshAction); } @@ -283,7 +267,7 @@ namespace Umbraco.Core CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout, Func getCacheItem) { - return _runtimeCache.GetCacheItem(cacheKey, getCacheItem, timeout, false, priority, refreshAction); + return RuntimeCache.GetCacheItem(cacheKey, getCacheItem, timeout, false, priority, refreshAction); } @@ -306,7 +290,7 @@ namespace Umbraco.Core TimeSpan timeout, Func getCacheItem) { - var cache = _runtimeCache as HttpRuntimeCacheProvider; + var cache = RuntimeCache as HttpRuntimeCacheProvider; if (cache != null) { var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency); @@ -330,7 +314,7 @@ namespace Umbraco.Core CacheDependency cacheDependency, Func getCacheItem) { - var cache = _runtimeCache as HttpRuntimeCacheProvider; + var cache = RuntimeCache as HttpRuntimeCacheProvider; if (cache != null) { var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), null, false, priority, null, cacheDependency); @@ -352,7 +336,7 @@ namespace Umbraco.Core CacheItemPriority priority, Func getCacheItem) { - _runtimeCache.InsertCacheItem(cacheKey, getCacheItem, priority: priority); + RuntimeCache.InsertCacheItem(cacheKey, getCacheItem, priority: priority); } @@ -371,7 +355,7 @@ namespace Umbraco.Core TimeSpan timeout, Func getCacheItem) { - _runtimeCache.InsertCacheItem(cacheKey, getCacheItem, timeout, priority: priority); + RuntimeCache.InsertCacheItem(cacheKey, getCacheItem, timeout, priority: priority); } /// @@ -390,7 +374,7 @@ namespace Umbraco.Core TimeSpan timeout, Func getCacheItem) { - var cache = _runtimeCache as HttpRuntimeCacheProvider; + var cache = RuntimeCache as HttpRuntimeCacheProvider; if (cache != null) { cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, null, cacheDependency); @@ -416,7 +400,7 @@ namespace Umbraco.Core TimeSpan? timeout, Func getCacheItem) { - var cache = _runtimeCache as HttpRuntimeCacheProvider; + var cache = RuntimeCache as HttpRuntimeCacheProvider; if (cache != null) { cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency); diff --git a/src/Umbraco.Core/Persistence/RepositoryFactory.cs b/src/Umbraco.Core/Persistence/RepositoryFactory.cs index 9bb1d8d11c..1c1e551d34 100644 --- a/src/Umbraco.Core/Persistence/RepositoryFactory.cs +++ b/src/Umbraco.Core/Persistence/RepositoryFactory.cs @@ -31,29 +31,27 @@ namespace Umbraco.Core.Persistence //if (sqlSyntax == null) throw new ArgumentNullException("sqlSyntax"); if (settings == null) throw new ArgumentNullException("settings"); - _cacheHelper = cacheHelper; + _cacheHelper = cacheHelper; //IMPORTANT: We will force the DeepCloneRuntimeCacheProvider to be used here which is a wrapper for the underlying // runtime cache to ensure that anything that can be deep cloned in/out is done so, this also ensures that our tracks // changes entities are reset. if ((_cacheHelper.RuntimeCache is DeepCloneRuntimeCacheProvider) == false) { - var originalHelper = cacheHelper; - - _cacheHelper = new CacheHelper( - new DeepCloneRuntimeCacheProvider(originalHelper.RuntimeCache), - originalHelper.StaticCache, - originalHelper.RequestCache, - new IsolatedRuntimeCache(type => - { - var cache = originalHelper.IsolatedRuntimeCache.GetOrCreateCache(type); - return (cache is DeepCloneRuntimeCacheProvider) == false - //wrap the original if it's not DeepCloneRuntimeCacheProvider - ? new DeepCloneRuntimeCacheProvider(cache) - : cache; - })); + var origRuntimeCache = cacheHelper.RuntimeCache; + _cacheHelper.RuntimeCache = new DeepCloneRuntimeCacheProvider(origRuntimeCache); } - + //If the factory for isolated cache doesn't return DeepCloneRuntimeCacheProvider, then ensure it does + if (_cacheHelper.IsolatedRuntimeCache.CacheFactory.Method.ReturnType != typeof (DeepCloneRuntimeCacheProvider)) + { + var origFactory = cacheHelper.IsolatedRuntimeCache.CacheFactory; + _cacheHelper.IsolatedRuntimeCache.CacheFactory = type => + { + var cache = origFactory(type); + return new DeepCloneRuntimeCacheProvider(cache); + }; + } + _noCache = CacheHelper.CreateDisabledCacheHelper(); _logger = logger; _sqlSyntax = sqlSyntax; diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index f84d204bb1..dcf1e98be4 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -39,6 +39,7 @@ using Umbraco.Web.Scheduling; using Umbraco.Web.UI.JavaScript; using Umbraco.Web.WebApi; using umbraco.BusinessLogic; +using Umbraco.Core.Cache; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Publishing; @@ -240,7 +241,19 @@ namespace Umbraco.Web protected override CacheHelper CreateApplicationCache() { //create a web-based cache helper - return new CacheHelper(); + var cacheHelper = new CacheHelper( + //we need to have the dep clone runtime cache provider to ensure + //all entities are cached properly (cloned in and cloned out) + new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), + new StaticCacheProvider(), + //we have no request based cache when not running in web-based context + new NullCacheProvider(), + new IsolatedRuntimeCache(type => + //we need to have the dep clone runtime cache provider to ensure + //all entities are cached properly (cloned in and cloned out) + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + + return cacheHelper; } ///