diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs index 3cff4f0298..5f30c08ce7 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs @@ -98,10 +98,45 @@ namespace Umbraco.Core.Models.PublishedContent #endregion - + #region Cache + + // these methods are called by ContentTypeCacheRefresher and DataTypeCacheRefresher + + internal static void ClearAll() + { + Logging.LogHelper.Debug("Clear all."); + // ok and faster to do it by types, assuming noone else caches PublishedContentType instances + //ApplicationContext.Current.ApplicationCache.ClearStaticCacheByKeySearch("PublishedContentType_"); + ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes(); + } + + internal static void ClearContentType(int id) + { + Logging.LogHelper.Debug("Clear content type w/id {0}.", () => id); + // requires a predicate because the key does not contain the ID + // faster than key strings comparisons anyway + ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes( + (key, value) => value.Id == id); + } + + internal static void ClearDataType(int id) + { + Logging.LogHelper.Debug("Clear data type w/id {0}.", () => id); + // there is no recursion to handle here because a PublishedContentType contains *all* its + // properties ie both its own properties and those that were inherited (it's based upon an + // IContentTypeComposition) and so every PublishedContentType having a property based upon + // the cleared data type, be it local or inherited, will be cleared. + ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes( + (key, value) => value.PropertyTypes.Any(x => x.DataTypeId == id)); + } + public static PublishedContentType Get(PublishedItemType itemType, string alias) { - var type = CreatePublishedContentType(itemType, alias); + var key = string.Format("PublishedContentType_{0}_{1}", + itemType.ToString().ToLowerInvariant(), alias.ToLowerInvariant()); + + var type = ApplicationContext.Current.ApplicationCache.StaticCache.GetCacheItem(key, + () => CreatePublishedContentType(itemType, alias)); return type; } @@ -134,8 +169,21 @@ namespace Umbraco.Core.Models.PublishedContent return new PublishedContentType(contentType); } - // for unit tests - internal static Func GetPublishedContentTypeCallback { get; set; } - + // for unit tests - changing the callback must reset the cache obviously + private static Func _getPublishedContentTypeCallBack; + internal static Func GetPublishedContentTypeCallback + { + get { return _getPublishedContentTypeCallBack; } + set + { + // see note above + //ClearAll(); + ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheByKeySearch("PublishedContentType_"); + + _getPublishedContentTypeCallBack = value; + } + } + + #endregion } } diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs index f4b1597a7d..22d453e150 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs @@ -230,13 +230,13 @@ namespace Umbraco.Core.Models.PublishedContent { _sourceCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.Source); _objectCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.Object); - _objectCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.XPath); + _xpathCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.XPath); } else { _sourceCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.Source); _objectCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.Object); - _objectCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.XPath); + _xpathCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.XPath); } if (_objectCacheLevel < _sourceCacheLevel) _objectCacheLevel = _sourceCacheLevel; if (_xpathCacheLevel < _sourceCacheLevel) _xpathCacheLevel = _sourceCacheLevel; diff --git a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs index c44b3f2b51..44a6efe9ff 100644 --- a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs @@ -141,7 +141,9 @@ namespace Umbraco.Web.Cache ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.ContentTypeCacheKey); //clear static object cache global::umbraco.cms.businesslogic.ContentType.RemoveAllDataTypeCache(); - + + PublishedContentType.ClearAll(); + base.RefreshAll(); } @@ -278,7 +280,9 @@ namespace Umbraco.Web.Cache //clears the dictionary object cache of the legacy ContentType global::umbraco.cms.businesslogic.ContentType.RemoveFromDataTypeCache(payload.Alias); - + + PublishedContentType.ClearContentType(payload.Id); + //need to recursively clear the cache for each child content type foreach (var descendant in payload.DescendantPayloads) { diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs index 173f4dcb86..11b3ab6294 100644 --- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -108,6 +108,7 @@ namespace Umbraco.Web.Cache if (dataTypeCache) dataTypeCache.Result.ClearCacheByKeySearch(string.Format("{0}{1}", CacheKeys.DataTypePreValuesCacheKey, payload.Id)); + PublishedContentType.ClearDataType(payload.Id); }); base.Refresh(jsonPayload);