Facade - Cleanup access to 'current'

This commit is contained in:
Stephan
2016-05-30 19:54:36 +02:00
parent bc45dd8d6a
commit 7c5542dca3
40 changed files with 384 additions and 348 deletions

View File

@@ -177,7 +177,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
// we add this check - we look for the document matching "/" and if it's not us, then
// we do not hide the top level path
// it has to be taken care of in GetByRoute too so if
// "/foo" fails (looking for "/*/foo") we try also "/foo".
// "/foo" fails (looking for "/*/foo") we try also "/foo".
// this does not make much sense anyway esp. if both "/foo/" and "/bar/foo" exist, but
// that's the way it works pre-4.10 and we try to be backward compat for the time being
if (content.Parent == null)
@@ -222,12 +222,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
if (FacadeService.CacheContentCacheRoots == false)
return GetAtRootNoCache(preview);
var facade = Facade.Current;
var cache = (facade == null)
? null
: (preview == false || FacadeService.FullCacheWhenPreviewing
? facade.SnapshotCache
: facade.FacadeCache);
var cache = preview == false || FacadeService.FullCacheWhenPreviewing
? _snapshotCache
: _facadeCache;
if (cache == null)
return GetAtRootNoCache(preview);
@@ -253,7 +250,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
internal static IPublishedContent GetPublishedContentAsPreviewing(IPublishedContent content /*, bool preview*/)
{
if (content == null /*|| preview == false*/) return null; //content;
// an object in the cache is either an IPublishedContentOrMedia,
// or a model inheriting from PublishedContentExtended - in which
// case we need to unwrap to get to the original IPublishedContentOrMedia.

View File

@@ -33,10 +33,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
int level, string path, int sortOrder,
int parentContentId,
DateTime createDate, int creatorId,
ContentData draftData, ContentData publishedData)
ContentData draftData, ContentData publishedData,
IFacadeAccessor facadeAccessor)
: this(id, uid, level, path, sortOrder, parentContentId, createDate, creatorId)
{
SetContentTypeAndData(contentType, draftData, publishedData);
SetContentTypeAndData(contentType, draftData, publishedData, facadeAccessor);
}
// 2-phases ctor, phase 1
@@ -58,7 +59,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
}
// two-phase ctor, phase 2
public void SetContentTypeAndData(PublishedContentType contentType, ContentData draftData, ContentData publishedData)
public void SetContentTypeAndData(PublishedContentType contentType, ContentData draftData, ContentData publishedData, IFacadeAccessor facadeAccessor)
{
ContentType = contentType;
@@ -66,13 +67,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
throw new ArgumentException("Both draftData and publishedData cannot be null at the same time.");
if (draftData != null)
Draft = new PublishedContent(this, draftData).CreateModel();
Draft = new PublishedContent(this, draftData, facadeAccessor).CreateModel();
if (publishedData != null)
Published = new PublishedContent(this, publishedData).CreateModel();
Published = new PublishedContent(this, publishedData, facadeAccessor).CreateModel();
}
// clone parent
private ContentNode(ContentNode origin)
private ContentNode(ContentNode origin, IFacadeAccessor facadeAccessor)
{
// everything is the same, except for the child items
// list which is a clone of the original list
@@ -90,14 +91,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
var originDraft = origin.Draft == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Draft);
var originPublished = origin.Published == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Published);
Draft = originDraft == null ? null : new PublishedContent(this, originDraft).CreateModel();
Published = originPublished == null ? null : new PublishedContent(this, originPublished).CreateModel();
Draft = originDraft == null ? null : new PublishedContent(this, originDraft, facadeAccessor).CreateModel();
Published = originPublished == null ? null : new PublishedContent(this, originPublished, facadeAccessor).CreateModel();
ChildContentIds = new List<int>(origin.ChildContentIds); // needs to be *another* list
}
// clone with new content type
public ContentNode(ContentNode origin, PublishedContentType contentType)
public ContentNode(ContentNode origin, PublishedContentType contentType, IFacadeAccessor facadeAccessor)
{
Id = origin.Id;
Uid = origin.Uid;
@@ -112,8 +113,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
var originDraft = origin.Draft == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Draft);
var originPublished = origin.Published == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Published);
Draft = originDraft == null ? null : new PublishedContent(this, originDraft._contentData).CreateModel();
Published = originPublished == null ? null : new PublishedContent(this, originPublished._contentData).CreateModel();
Draft = originDraft == null ? null : new PublishedContent(this, originDraft._contentData, facadeAccessor).CreateModel();
Published = originPublished == null ? null : new PublishedContent(this, originPublished._contentData, facadeAccessor).CreateModel();
ChildContentIds = origin.ChildContentIds; // can be the *same* list FIXME oh really?
}
@@ -135,9 +136,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
public IPublishedContent Draft;
public IPublishedContent Published;
public ContentNode CloneParent()
public ContentNode CloneParent(IFacadeAccessor facadeAccessor)
{
return new ContentNode(this);
return new ContentNode(this, facadeAccessor);
}
public ContentNodeKit ToKit()

View File

@@ -11,11 +11,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
public ContentData DraftData;
public ContentData PublishedData;
public bool IsEmpty { get { return Node == null; } }
public bool IsEmpty => Node == null;
public void Build(PublishedContentType contentType)
public void Build(PublishedContentType contentType, IFacadeAccessor facadeAccessor)
{
Node.SetContentTypeAndData(contentType, DraftData, PublishedData);
Node.SetContentTypeAndData(contentType, DraftData, PublishedData, facadeAccessor);
}
}
}

View File

@@ -17,6 +17,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
// most of the snapshots management code, etc is an exact copy
// SnapDictionary has unit tests to ensure it all works correctly
private readonly IFacadeAccessor _facadeAccessor;
private readonly ConcurrentDictionary<int, LinkedNode<ContentNode>> _contentNodes;
private readonly ConcurrentDictionary<int, LinkedNode<object>> _contentRootNodes;
private readonly ConcurrentDictionary<int, LinkedNode<PublishedContentType>> _contentTypesById;
@@ -40,8 +41,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
#region Ctor
public ContentStore2(ILogger logger, BPlusTree<int, ContentNodeKit> localDb = null)
public ContentStore2(IFacadeAccessor facadeAccessor, ILogger logger, BPlusTree<int, ContentNodeKit> localDb = null)
{
_facadeAccessor = facadeAccessor;
_logger = logger;
_localDb = localDb;
@@ -270,7 +272,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
_contentNodes.TryGetValue(id, out link);
if (link == null || link.Value == null)
continue;
var node = new ContentNode(link.Value, contentType);
var node = new ContentNode(link.Value, contentType, _facadeAccessor);
SetValueLocked(_contentNodes, id, node);
if (_localDb != null)
_localDb[id] = node.ToKit();
@@ -302,7 +304,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
_contentTypeNodes[kit.ContentTypeId].Add(kit.Node.Id);
// and use
kit.Build(link.Value);
kit.Build(link.Value, _facadeAccessor);
return true;
}
@@ -511,7 +513,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
var link = GetParentLink(content);
var parent = link.Value;
if (link.Gen < _liveGen)
parent = parent.CloneParent();
parent = parent.CloneParent(_facadeAccessor);
parent.ChildContentIds.Remove(content.Id);
if (link.Gen < _liveGen)
SetValueLocked(_contentNodes, parent.Id, parent);
@@ -541,7 +543,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
var link = GetParentLink(content);
var parent = link.Value;
if (link.Gen < _liveGen)
parent = parent.CloneParent();
parent = parent.CloneParent(_facadeAccessor);
parent.ChildContentIds.Add(content.Id);
if (link.Gen < _liveGen)
SetValueLocked(_contentNodes, parent.Id, parent);

View File

@@ -1,7 +1,5 @@
using System;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Web.PublishedCache.NuCache
{
@@ -37,75 +35,34 @@ namespace Umbraco.Web.PublishedCache.NuCache
}
}
private FacadeElements Elements
{
get
{
// no lock - facades are single-thread
return _elements ?? (_elements = _service.GetElements(_defaultPreview));
}
}
private FacadeElements Elements => _elements ?? (_elements = _service.GetElements(_defaultPreview));
public void Resync()
{
// no lock - facades are single-thread
if (_elements != null)
_elements.Dispose();
_elements?.Dispose();
_elements = null;
}
#endregion
#region Current - for tests
private static Func<Facade> _getCurrentFacadeFunc = () =>
{
#if DEBUG
if (FacadeServiceResolver.HasCurrent == false) return null;
var service = FacadeServiceResolver.Current.Service as FacadeService;
if (service == null) return null;
return (Facade) service.GetFacadeFunc();
#else
return (Facade) ((FacadeService) FacadeServiceResolver.Current.Service).GetFacadeFunc();
#endif
};
public static Func<Facade> GetCurrentFacadeFunc
{
get { return _getCurrentFacadeFunc; }
set
{
using (Resolution.Configuration)
{
_getCurrentFacadeFunc = value;
}
}
}
public static Facade Current
{
get { return _getCurrentFacadeFunc(); }
}
#endregion
#region Caches
public ICacheProvider FacadeCache { get; private set; }
public ICacheProvider SnapshotCache { get { return Elements.SnapshotCache; } }
public ICacheProvider SnapshotCache => Elements.SnapshotCache;
#endregion
#region IFacade
public IPublishedContentCache ContentCache { get { return Elements.ContentCache; } }
public IPublishedContentCache ContentCache => Elements.ContentCache;
public IPublishedMediaCache MediaCache { get { return Elements.MediaCache; } }
public IPublishedMediaCache MediaCache => Elements.MediaCache;
public IPublishedMemberCache MemberCache { get { return Elements.MemberCache; } }
public IPublishedMemberCache MemberCache => Elements.MemberCache;
public IDomainCache DomainCache { get { return Elements.DomainCache; } }
public IDomainCache DomainCache => Elements.DomainCache;
#endregion
@@ -117,8 +74,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
{
if (_disposed) return;
_disposed = true;
if (_elements != null)
_elements.Dispose();
_elements?.Dispose();
}
#endregion

View File

@@ -32,6 +32,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
{
class FacadeService : FacadeServiceBase
{
private readonly IFacadeAccessor _facadeAccessor;
private readonly ServiceContext _serviceContext;
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly Database _dataSource;
@@ -70,8 +71,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
#region Constructors
public FacadeService(Options options, MainDom mainDom, ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, ILogger logger)
public FacadeService(Options options, MainDom mainDom, ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, IFacadeAccessor facadeAccessor, ILogger logger)
: base(facadeAccessor)
{
_facadeAccessor = facadeAccessor;
_serviceContext = serviceContext;
_uowProvider = uowProvider;
_dataSource = new Database();
@@ -120,13 +123,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
// stores are created with a db so they can write to it, but they do not read from it,
// stores need to be populated, happens in OnResolutionFrozen which uses _localDbExists to
// figure out whether it can read the dbs or it should populate them from sql
_contentStore = new ContentStore2(logger, _localContentDb);
_mediaStore = new ContentStore2(logger, _localMediaDb);
_contentStore = new ContentStore2(facadeAccessor, logger, _localContentDb);
_mediaStore = new ContentStore2(facadeAccessor, logger, _localMediaDb);
}
else
{
_contentStore = new ContentStore2(logger);
_mediaStore = new ContentStore2(logger);
_contentStore = new ContentStore2(facadeAccessor, logger);
_mediaStore = new ContentStore2(facadeAccessor, logger);
}
_domainStore = new SnapDictionary<int, Domain>();
@@ -477,7 +480,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
publishedChanged = publishedChanged2;
if (draftChanged || publishedChanged)
Facade.Current.Resync();
((Facade)CurrentFacade).Resync();
}
private void NotifyLocked(IEnumerable<ContentCacheRefresher.JsonPayload> payloads, out bool draftChanged, out bool publishedChanged)
@@ -575,7 +578,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
anythingChanged = anythingChanged2;
if (anythingChanged)
Facade.Current.Resync();
((Facade)CurrentFacade).Resync();
}
private void NotifyLocked(IEnumerable<MediaCacheRefresher.JsonPayload> payloads, out bool anythingChanged)
@@ -697,7 +700,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
RefreshMediaTypesLocked(removedIds, refreshedIds);
});
Facade.Current.Resync();
((Facade)CurrentFacade).Resync();
}
public override void Notify(DataTypeCacheRefresher.JsonPayload[] payloads)
@@ -735,7 +738,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
}
}));
Facade.Current.Resync();
((Facade) CurrentFacade).Resync();
}
public override void Notify(DomainCacheRefresher.JsonPayload[] payloads)
@@ -926,8 +929,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
return new Facade.FacadeElements
{
ContentCache = new ContentCache(previewDefault, contentSnap, facadeCache, snapshotCache, new DomainHelper(domainCache)),
MediaCache = new MediaCache(previewDefault, mediaSnap),
MemberCache = new MemberCache(previewDefault, _serviceContext.MemberService, _serviceContext.DataTypeService, memberTypeCache),
MediaCache = new MediaCache(previewDefault, mediaSnap, facadeCache, snapshotCache),
MemberCache = new MemberCache(previewDefault, facadeCache, _serviceContext.MemberService, _serviceContext.DataTypeService, memberTypeCache, _facadeAccessor),
DomainCache = domainCache,
FacadeCache = facadeCache,
SnapshotCache = snapshotCache

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Xml.XPath;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Xml;
@@ -14,13 +15,17 @@ namespace Umbraco.Web.PublishedCache.NuCache
class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableData, IDisposable
{
private readonly ContentStore2.Snapshot _snapshot;
private readonly ICacheProvider _facadeCache;
private readonly ICacheProvider _snapshotCache;
#region Constructors
public MediaCache(bool previewDefault, ContentStore2.Snapshot snapshot)
public MediaCache(bool previewDefault, ContentStore2.Snapshot snapshot, ICacheProvider facadeCache, ICacheProvider snapshotCache)
: base(previewDefault)
{
_snapshot = snapshot;
_facadeCache = facadeCache;
_snapshotCache = snapshotCache;
}
#endregion
@@ -30,7 +35,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
public override IPublishedContent GetById(bool preview, int contentId)
{
var n = _snapshot.Get(contentId);
return n == null ? null : n.Published;
return n?.Published;
}
public override bool HasById(bool preview, int contentId)
@@ -44,12 +49,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
if (FacadeService.CacheContentCacheRoots == false)
return GetAtRootNoCache(preview);
var facade = Facade.Current;
var cache = (facade == null)
? null
: (preview == false || FacadeService.FullCacheWhenPreviewing
? facade.SnapshotCache
: facade.FacadeCache);
var cache = preview == false || FacadeService.FullCacheWhenPreviewing
? _snapshotCache
: _facadeCache;
if (cache == null)
return GetAtRootNoCache(preview);

View File

@@ -15,13 +15,17 @@ namespace Umbraco.Web.PublishedCache.NuCache
{
class MemberCache : IPublishedMemberCache, INavigableData
{
private readonly IFacadeAccessor _facadeAccessor;
private readonly ICacheProvider _facadeCache;
private readonly IMemberService _memberService;
private readonly IDataTypeService _dataTypeService;
private readonly PublishedContentTypeCache _contentTypeCache;
private readonly bool _previewDefault;
public MemberCache(bool previewDefault, IMemberService memberService, IDataTypeService dataTypeService, PublishedContentTypeCache contentTypeCache)
public MemberCache(bool previewDefault, ICacheProvider facadeCache, IMemberService memberService, IDataTypeService dataTypeService, PublishedContentTypeCache contentTypeCache, IFacadeAccessor facadeAccessor)
{
_facadeCache = facadeCache;
_facadeAccessor = facadeAccessor;
_memberService = memberService;
_dataTypeService = dataTypeService;
_previewDefault = previewDefault;
@@ -38,11 +42,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
// : (T) cache.GetCacheItem(cacheKey);
//}
private static T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem)
private T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem)
where T : class
{
var facade = Facade.Current;
var cache = facade == null ? null : facade.FacadeCache;
var cache = _facadeCache;
return cache == null
? getCacheItem()
: cache.GetCacheItem<T>(cacheKey, getCacheItem);
@@ -68,14 +71,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
var member = _memberService.GetById(memberId);
return member == null
? null
: PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault);
: PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _facadeAccessor);
});
}
private IPublishedContent /*IPublishedMember*/ GetById(IMember member, bool previewing)
{
return GetCacheItem(CacheKeys.MemberCacheMember("ById", _previewDefault, member.Id), () =>
PublishedMember.Create(member, GetContentType(member.ContentTypeId), previewing));
PublishedMember.Create(member, GetContentType(member.ContentTypeId), previewing, _facadeAccessor));
}
public IPublishedContent /*IPublishedMember*/ GetByProviderKey(object key)
@@ -110,7 +113,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
public IPublishedContent /*IPublishedMember*/ GetByMember(IMember member)
{
return PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault);
return PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _facadeAccessor);
}
public IEnumerable<IPublishedContent> GetAtRoot(bool preview)
@@ -118,7 +121,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
// because members are flat (not a tree) everything is at root
// because we're loading everything... let's just not cache?
var members = _memberService.GetAllMembers();
return members.Select(m => PublishedMember.Create(m, GetContentType(m.ContentTypeId), preview));
return members.Select(m => PublishedMember.Create(m, GetContentType(m.ContentTypeId), preview, _facadeAccessor));
}
public XPathNavigator CreateNavigator()

View File

@@ -11,6 +11,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
[XmlType(Namespace = "http://umbraco.org/webservices/")]
class Property : PublishedPropertyBase
{
private readonly IFacadeAccessor _facadeAccessor;
private readonly object _dataValue;
private readonly Guid _contentUid;
private readonly bool _isPreviewing;
@@ -23,12 +24,12 @@ namespace Umbraco.Web.PublishedCache.NuCache
private string _recurseCacheKey;
// initializes a published content property with no value
public Property(PublishedPropertyType propertyType, PublishedContent content)
: this(propertyType, content, null)
public Property(PublishedPropertyType propertyType, PublishedContent content, IFacadeAccessor facadeAccessor)
: this(propertyType, content, null, facadeAccessor)
{ }
// initializes a published content property with a value
public Property(PublishedPropertyType propertyType, PublishedContent content, object valueSource)
public Property(PublishedPropertyType propertyType, PublishedContent content, object valueSource, IFacadeAccessor facadeAccessor)
: base(propertyType)
{
_dataValue = valueSource;
@@ -36,6 +37,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
var inner = PublishedContent.UnwrapIPublishedContent(content);
_isPreviewing = inner.IsPreviewing;
_isMember = content.ContentType.ItemType == PublishedItemType.Member;
_facadeAccessor = facadeAccessor;
}
// clone for previewing as draft a published content that is published and has no draft
@@ -46,6 +48,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
_contentUid = origin._contentUid;
_isPreviewing = true;
_isMember = origin._isMember;
_facadeAccessor = origin._facadeAccessor;
}
// detached
@@ -58,10 +61,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
// _isMember = isMember;
//}
public override bool HasValue
{
get { return _dataValue != null && ((_dataValue is string) == false || string.IsNullOrWhiteSpace((string)_dataValue) == false); }
}
public override bool HasValue => _dataValue != null
&& ((_dataValue is string) == false || string.IsNullOrWhiteSpace((string)_dataValue) == false);
private class ValueSet
{
@@ -73,15 +74,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
public object XPath;
}
internal string RecurseCacheKey
{
get { return _recurseCacheKey ?? (_recurseCacheKey = CacheKeys.PropertyRecurse(_contentUid, PropertyTypeAlias, _isPreviewing)); }
}
internal string RecurseCacheKey => _recurseCacheKey
?? (_recurseCacheKey = CacheKeys.PropertyRecurse(_contentUid, PropertyTypeAlias, _isPreviewing));
internal string ValueSetCacheKey
{
get { return _valueSetCacheKey ?? (_valueSetCacheKey = CacheKeys.PropertyValueSet(_contentUid, PropertyTypeAlias, _isPreviewing)); }
}
internal string ValueSetCacheKey => _valueSetCacheKey
?? (_valueSetCacheKey = CacheKeys.PropertyValueSet(_contentUid, PropertyTypeAlias, _isPreviewing));
private ValueSet GetValueSet(PropertyCacheLevel cacheLevel)
{
@@ -103,7 +100,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
// snapshot cache (if we don't want to pollute the snapshot cache with short-lived
// data) depending on settings
// for members, always cache in the facade cache - never pollute snapshot cache
facade = Facade.Current;
facade = (Facade) _facadeAccessor.Facade;
cache = facade == null
? null
: ((_isPreviewing == false || FacadeService.FullCacheWhenPreviewing) && (_isMember == false)
@@ -113,8 +110,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
break;
case PropertyCacheLevel.Request:
// cache within the facade cache
facade = Facade.Current;
cache = facade == null ? null : facade.FacadeCache;
facade = (Facade)_facadeAccessor.Facade;
cache = facade?.FacadeCache;
valueSet = GetValueSet(cache);
break;
default:
@@ -141,10 +138,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
return valueSet.Source;
}
public override object DataValue
{
get { return _dataValue; }
}
public override object DataValue => _dataValue;
public override object Value
{

View File

@@ -12,30 +12,29 @@ namespace Umbraco.Web.PublishedCache.NuCache
{
internal class PublishedContent : PublishedContentWithKeyBase
{
private readonly IFacadeAccessor _facadeAccessor;
private readonly ContentNode _contentNode;
// ReSharper disable once InconsistentNaming
internal readonly ContentData _contentData; // internal for ContentNode cloning
private readonly IPublishedProperty[] _properties;
private readonly string _urlName;
private readonly bool _isPreviewing;
#region Constructors
public PublishedContent(ContentNode contentNode, ContentData contentData)
public PublishedContent(ContentNode contentNode, ContentData contentData, IFacadeAccessor facadeAccessor)
{
_contentNode = contentNode;
_contentData = contentData;
_facadeAccessor = facadeAccessor;
_urlName = _contentData.Name.ToUrlSegment();
_isPreviewing = _contentData.Published == false;
_properties = CreateProperties(this, contentData.Properties);
IsPreviewing = _contentData.Published == false;
PropertiesArray = CreateProperties(this, contentData.Properties);
}
private static string GetProfileNameById(int id)
private string GetProfileNameById(int id)
{
var facade = Facade.Current;
var cache = facade == null ? null : facade.FacadeCache;
var cache = GetCurrentFacadeCache();
return cache == null
? GetProfileNameByIdNoCache(id)
: (string) cache.GetCacheItem(CacheKeys.ProfileName(id), () => GetProfileNameByIdNoCache(id));
@@ -45,8 +44,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
{
#if DEBUG
var context = ApplicationContext.Current;
var servicesContext = context == null ? null : context.Services;
var userService = servicesContext == null ? null : servicesContext.UserService;
var servicesContext = context?.Services;
var userService = servicesContext?.UserService;
if (userService == null) return "[null]"; // for tests
#else
// we don't want each published content to hold a reference to the service
@@ -54,10 +53,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
var userService = ApplicationContext.Current.Services.UserService;
#endif
var user = userService.GetProfileById(id);
return user == null ? null : user.Name;
return user?.Name;
}
private static IPublishedProperty[] CreateProperties(PublishedContent content, IDictionary<string, object> values)
private IPublishedProperty[] CreateProperties(PublishedContent content, IDictionary<string, object> values)
{
return content._contentNode.ContentType
.PropertyTypes
@@ -65,38 +64,40 @@ namespace Umbraco.Web.PublishedCache.NuCache
{
object value;
return values.TryGetValue(propertyType.PropertyTypeAlias, out value)
? (IPublishedProperty) new Property(propertyType, content, value)
: (IPublishedProperty) new Property(propertyType, content);
? new Property(propertyType, content, value, _facadeAccessor) as IPublishedProperty
: new Property(propertyType, content, _facadeAccessor) as IPublishedProperty;
})
.ToArray();
}
// (see ContentNode.CloneParent)
public PublishedContent(ContentNode contentNode, PublishedContent origin)
public PublishedContent(ContentNode contentNode, PublishedContent origin, IFacadeAccessor facadeAccessor)
{
_contentNode = contentNode;
_facadeAccessor = facadeAccessor;
_contentData = origin._contentData;
_urlName = origin._urlName;
_isPreviewing = origin._isPreviewing;
IsPreviewing = origin.IsPreviewing;
// here is the main benefit: we do not re-create properties so if anything
// is cached locally, we share the cache - which is fine - if anything depends
// on the tree structure, it should not be cached locally to begin with
_properties = origin._properties;
PropertiesArray = origin.PropertiesArray;
}
// clone for previewing as draft a published content that is published and has no draft
private PublishedContent(PublishedContent origin)
private PublishedContent(PublishedContent origin, IFacadeAccessor facadeAccessor)
{
_facadeAccessor = facadeAccessor;
_contentNode = origin._contentNode;
_contentData = origin._contentData;
_urlName = origin._urlName;
_isPreviewing = true;
IsPreviewing = true;
// clone properties so _isPreviewing is true
_properties = origin._properties.Select(x => (IPublishedProperty) new Property((Property) x)).ToArray();
PropertiesArray = origin.PropertiesArray.Select(x => (IPublishedProperty) new Property((Property) x)).ToArray();
}
#endregion
@@ -128,14 +129,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
}
}
private static IPublishedContent GetContentById(bool previewing, int id)
private IPublishedContent GetContentById(bool previewing, int id)
{
return _getContentByIdFunc(Facade.Current, previewing, id);
return _getContentByIdFunc(_facadeAccessor.Facade, previewing, id);
}
private static IEnumerable<IPublishedContent> GetContentByIds(bool previewing, IEnumerable<int> ids)
private IEnumerable<IPublishedContent> GetContentByIds(bool previewing, IEnumerable<int> ids)
{
var facade = Facade.Current;
var facade = _facadeAccessor.Facade;
// beware! the loop below CANNOT be converted to query such as:
//return ids.Select(x => _getContentByIdFunc(facade, previewing, x)).Where(x => x != null);
@@ -151,14 +152,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
}
}
private static IPublishedContent GetMediaById(bool previewing, int id)
private IPublishedContent GetMediaById(bool previewing, int id)
{
return _getMediaByIdFunc(Facade.Current, previewing, id);
return _getMediaByIdFunc(_facadeAccessor.Facade, previewing, id);
}
private static IEnumerable<IPublishedContent> GetMediaByIds(bool previewing, IEnumerable<int> ids)
private IEnumerable<IPublishedContent> GetMediaByIds(bool previewing, IEnumerable<int> ids)
{
var facade = Facade.Current;
var facade = _facadeAccessor.Facade;
// see note above for content
@@ -174,42 +175,30 @@ namespace Umbraco.Web.PublishedCache.NuCache
#region IPublishedContent
public override int Id { get { return _contentNode.Id; } }
public override Guid Key { get { return _contentNode.Uid; } }
public override int DocumentTypeId { get { return _contentNode.ContentType.Id; } }
public override string DocumentTypeAlias { get { return _contentNode.ContentType.Alias; } }
public override PublishedItemType ItemType { get { return _contentNode.ContentType.ItemType; } }
public override int Id => _contentNode.Id;
public override Guid Key => _contentNode.Uid;
public override int DocumentTypeId => _contentNode.ContentType.Id;
public override string DocumentTypeAlias => _contentNode.ContentType.Alias;
public override PublishedItemType ItemType => _contentNode.ContentType.ItemType;
public override string Name { get { return _contentData.Name; } }
public override int Level { get { return _contentNode.Level; } }
public override string Path { get { return _contentNode.Path; } }
public override int SortOrder { get { return _contentNode.SortOrder; } }
public override Guid Version { get { return _contentData.Version; } }
public override int TemplateId { get { return _contentData.TemplateId; } }
public override string Name => _contentData.Name;
public override int Level => _contentNode.Level;
public override string Path => _contentNode.Path;
public override int SortOrder => _contentNode.SortOrder;
public override Guid Version => _contentData.Version;
public override int TemplateId => _contentData.TemplateId;
public override string UrlName { get { return _urlName; } }
public override string UrlName => _urlName;
public override DateTime CreateDate { get { return _contentNode.CreateDate; } }
public override DateTime UpdateDate { get { return _contentData.VersionDate; } }
public override DateTime CreateDate => _contentNode.CreateDate;
public override DateTime UpdateDate => _contentData.VersionDate;
public override int CreatorId { get { return _contentNode.CreatorId; } }
public override string CreatorName { get { return GetProfileNameById(_contentNode.CreatorId); } }
public override int WriterId { get { return _contentData.WriterId; } }
public override string WriterName { get { return GetProfileNameById(_contentData.WriterId); } }
public override int CreatorId => _contentNode.CreatorId;
public override string CreatorName => GetProfileNameById(_contentNode.CreatorId);
public override int WriterId => _contentData.WriterId;
public override string WriterName => GetProfileNameById(_contentData.WriterId);
public override bool IsDraft { get { return _contentData.Published == false; } }
// beware what you use that one for - you don't want to cache its result
private ICacheProvider GetAppropriateFacadeCache()
{
var facade = Facade.Current;
var cache = facade == null
? null
: ((_isPreviewing == false || FacadeService.FullCacheWhenPreviewing) && (ItemType != PublishedItemType.Member)
? facade.SnapshotCache
: facade.FacadeCache);
return cache;
}
public override bool IsDraft => _contentData.Published == false;
public override IPublishedContent Parent
{
@@ -220,9 +209,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
switch (_contentNode.ContentType.ItemType)
{
case PublishedItemType.Content:
return GetContentById(_isPreviewing, _contentNode.ParentContentId);
return GetContentById(IsPreviewing, _contentNode.ParentContentId);
case PublishedItemType.Media:
return GetMediaById(_isPreviewing, _contentNode.ParentContentId);
return GetMediaById(IsPreviewing, _contentNode.ParentContentId);
default:
throw new Exception("oops");
}
@@ -231,16 +220,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
private string _childrenCacheKey;
private string ChildrenCacheKey
{
get { return _childrenCacheKey ?? (_childrenCacheKey = CacheKeys.PublishedContentChildren(Key, _isPreviewing)); }
}
private string ChildrenCacheKey => _childrenCacheKey ?? (_childrenCacheKey = CacheKeys.PublishedContentChildren(Key, IsPreviewing));
public override IEnumerable<IPublishedContent> Children
{
get
{
var cache = GetAppropriateFacadeCache();
var cache = GetAppropriateCurrentFacadeCache();
if (cache == null || FacadeService.CachePublishedContentChildren == false)
return GetChildren();
@@ -255,10 +241,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
switch (_contentNode.ContentType.ItemType)
{
case PublishedItemType.Content:
c = GetContentByIds(_isPreviewing, _contentNode.ChildContentIds);
c = GetContentByIds(IsPreviewing, _contentNode.ChildContentIds);
break;
case PublishedItemType.Media:
c = GetMediaByIds(_isPreviewing, _contentNode.ChildContentIds);
c = GetMediaByIds(IsPreviewing, _contentNode.ChildContentIds);
break;
default:
throw new Exception("oops");
@@ -272,12 +258,12 @@ namespace Umbraco.Web.PublishedCache.NuCache
// Q: perfs-wise, is it better than having the store managed an ordered list
}
public override ICollection<IPublishedProperty> Properties { get { return _properties; } }
public override ICollection<IPublishedProperty> Properties => PropertiesArray;
public override IPublishedProperty GetProperty(string alias)
{
var index = _contentNode.ContentType.GetPropertyIndex(alias);
var property = index < 0 ? null : _properties[index];
var property = index < 0 ? null : PropertiesArray[index];
return property;
}
@@ -286,7 +272,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
var property = GetProperty(alias);
if (recurse == false) return property;
var cache = GetAppropriateFacadeCache();
var cache = GetAppropriateCurrentFacadeCache();
if (cache == null)
return base.GetProperty(alias, true);
@@ -294,9 +280,28 @@ namespace Umbraco.Web.PublishedCache.NuCache
return (Property) cache.GetCacheItem(key, () => base.GetProperty(alias, true));
}
public override PublishedContentType ContentType
public override PublishedContentType ContentType => _contentNode.ContentType;
#endregion
#region Caching
// beware what you use that one for - you don't want to cache its result
private ICacheProvider GetAppropriateCurrentFacadeCache()
{
get { return _contentNode.ContentType; }
var facade = (Facade) _facadeAccessor.Facade;
var cache = facade == null
? null
: ((IsPreviewing == false || FacadeService.FullCacheWhenPreviewing) && (ItemType != PublishedItemType.Member)
? facade.SnapshotCache
: facade.FacadeCache);
return cache;
}
private ICacheProvider GetCurrentFacadeCache()
{
var facade = (Facade) _facadeAccessor.Facade;
return facade?.FacadeCache;
}
#endregion
@@ -304,38 +309,35 @@ namespace Umbraco.Web.PublishedCache.NuCache
#region Internal
// used by navigable content
internal IPublishedProperty[] PropertiesArray { get { return _properties; } }
internal IPublishedProperty[] PropertiesArray { get; }
// used by navigable content
internal int ParentId { get { return _contentNode.ParentContentId; } }
internal int ParentId => _contentNode.ParentContentId;
// used by navigable content
// includes all children, published or unpublished
// NavigableNavigator takes care of selecting those it wants
internal IList<int> ChildIds { get { return _contentNode.ChildContentIds; } }
internal IList<int> ChildIds => _contentNode.ChildContentIds;
// used by Property
// gets a value indicating whether the content or media exists in
// a previewing context or not, ie whether its Parent, Children, and
// properties should refer to published, or draft content
internal bool IsPreviewing { get { return _isPreviewing; } }
internal bool IsPreviewing { get; }
private string _asPreviewingCacheKey;
private string AsPreviewingCacheKey
{
get { return _asPreviewingCacheKey ?? (_asPreviewingCacheKey = CacheKeys.PublishedContentAsPreviewing(Key)); }
}
private string AsPreviewingCacheKey => _asPreviewingCacheKey ?? (_asPreviewingCacheKey = CacheKeys.PublishedContentAsPreviewing(Key));
// used by ContentCache
internal IPublishedContent AsPreviewingModel()
{
if (_isPreviewing)
if (IsPreviewing)
return this;
var cache = GetAppropriateFacadeCache();
if (cache == null) return new PublishedContent(this).CreateModel();
return (IPublishedContent) cache.GetCacheItem(AsPreviewingCacheKey, () => new PublishedContent(this).CreateModel());
var cache = GetAppropriateCurrentFacadeCache();
if (cache == null) return new PublishedContent(this, _facadeAccessor).CreateModel();
return (IPublishedContent) cache.GetCacheItem(AsPreviewingCacheKey, () => new PublishedContent(this, _facadeAccessor).CreateModel());
}
// used by Navigable.Source,...

View File

@@ -17,13 +17,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
{
private readonly IMember _member;
private PublishedMember(IMember member, ContentNode contentNode, ContentData contentData)
: base(contentNode, contentData)
private PublishedMember(IMember member, ContentNode contentNode, ContentData contentData, IFacadeAccessor facadeAccessor)
: base(contentNode, contentData, facadeAccessor)
{
_member = member;
}
public static IPublishedContent Create(IMember member, PublishedContentType contentType, bool previewing)
public static IPublishedContent Create(IMember member, PublishedContentType contentType, bool previewing, IFacadeAccessor facadeAccessor)
{
var d = new ContentData
{
@@ -40,7 +40,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
member.Level, member.Path, member.SortOrder,
member.ParentId,
member.CreateDate, member.CreatorId);
return new PublishedMember(member, n, d).CreateModel();
return new PublishedMember(member, n, d, facadeAccessor).CreateModel();
}
private static Dictionary<string, object> GetPropertyValues(PublishedContentType contentType, IMember member)