diff --git a/src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs index b65c6da840..00c2008da0 100644 --- a/src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs +++ b/src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs @@ -134,7 +134,11 @@ namespace Umbraco.Core.Cache lck.UpgradeToWriteLock(); - result = new Lazy(getCacheItem, LazyThreadSafetyMode.PublicationOnly); + result = new Lazy(getCacheItem, + //NOTE: This is required to not cache any exceptions that throw when the callback is executed. + // we want to ensure the callback is re-executed and not cached in the case that it might no + // longer throw an exception if runtime circumstances have changed. + LazyThreadSafetyMode.PublicationOnly); _cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback); } @@ -175,7 +179,12 @@ namespace Umbraco.Core.Cache // NOTE - here also we must insert a Lazy but we can evaluate it right now // and make sure we don't store a null value. - var result = new Lazy(getCacheItem, LazyThreadSafetyMode.PublicationOnly); + var result = new Lazy(getCacheItem, + //NOTE: This is required to not cache any exceptions that throw when the callback is executed. + // we want to ensure the callback is re-executed and not cached in the case that it might no + // longer throw an exception if runtime circumstances have changed. + LazyThreadSafetyMode.PublicationOnly); + var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache if (value == null) return; // do not store null values (backward compat) diff --git a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs index edf1ba5aa6..13b987df63 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs @@ -207,10 +207,14 @@ namespace Umbraco.Core.Cache result = MemoryCache.Get(cacheKey) as Lazy; if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null { - result = new Lazy(getCacheItem); var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); lck.UpgradeToWriteLock(); + result = new Lazy(getCacheItem, + //NOTE: This is required to not cache any exceptions that throw when the callback is executed. + // we want to ensure the callback is re-executed and not cached in the case that it might no + // longer throw an exception if runtime circumstances have changed. + LazyThreadSafetyMode.PublicationOnly); MemoryCache.Set(cacheKey, result, policy); } } @@ -227,7 +231,11 @@ namespace Umbraco.Core.Cache // NOTE - here also we must insert a Lazy but we can evaluate it right now // and make sure we don't store a null value. - var result = new Lazy(getCacheItem); + var result = new Lazy(getCacheItem, + //NOTE: This is required to not cache any exceptions that throw when the callback is executed. + // we want to ensure the callback is re-executed and not cached in the case that it might no + // longer throw an exception if runtime circumstances have changed. + LazyThreadSafetyMode.PublicationOnly); var value = result.Value; // force evaluation now if (value == null) return; // do not store null values (backward compat)