Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazily create content and models in NuCache #6346

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 40 additions & 26 deletions src/Umbraco.Web/PublishedCache/NuCache/ContentNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,11 @@ public void SetContentTypeAndData(IPublishedContentType contentType, ContentData
if (draftData == null && publishedData == null)
throw new ArgumentException("Both draftData and publishedData cannot be null at the same time.");

if (draftData != null)
{
DraftContent = new PublishedContent(this, draftData, publishedSnapshotAccessor, variationContextAccessor);
DraftModel = DraftContent.CreateModel();
}
_publishedSnapshotAccessor = publishedSnapshotAccessor;
_variationContextAccessor = variationContextAccessor;

if (publishedData != null)
{
PublishedContent = new PublishedContent(this, publishedData, publishedSnapshotAccessor, variationContextAccessor);
PublishedModel = PublishedContent.CreateModel();
}
_draftData = draftData;
_publishedData = publishedData;
}

// clone
Expand All @@ -105,14 +99,8 @@ public ContentNode(ContentNode origin, IPublishedContentType contentType = null)
CreateDate = origin.CreateDate;
CreatorId = origin.CreatorId;

var originDraft = origin.DraftContent;
var originPublished = origin.PublishedContent;

DraftContent = originDraft == null ? null : new PublishedContent(this, originDraft);
PublishedContent = originPublished == null ? null : new PublishedContent(this, originPublished);

DraftModel = DraftContent?.CreateModel();
PublishedModel = PublishedContent?.CreateModel();
_draftData = origin._draftData;
_publishedData = origin._publishedData;
}

// everything that is common to both draft and published versions
Expand All @@ -131,24 +119,50 @@ public ContentNode(ContentNode origin, IPublishedContentType contentType = null)
public readonly DateTime CreateDate;
public readonly int CreatorId;

// draft and published version (either can be null, but not both)
// are the direct PublishedContent instances
public PublishedContent DraftContent;
public PublishedContent PublishedContent;
private ContentData _draftData;
private ContentData _publishedData;
private IVariationContextAccessor _variationContextAccessor;
private IPublishedSnapshotAccessor _publishedSnapshotAccessor;

public bool HasPublished => _publishedData != null;
public bool HasPublishedCulture(string culture) => _publishedData != null && _publishedData.CultureInfos.ContainsKey(culture);

// draft and published version (either can be null, but not both)
// are models not direct PublishedContent instances
public IPublishedContent DraftModel;
public IPublishedContent PublishedModel;
private IPublishedContent _draftModel;
private IPublishedContent _publishedModel;

private IPublishedContent GetModel(ref IPublishedContent model, ContentData contentData)
{
if (model != null) return model;
if (contentData == null) return null;

// create the model - we want to be fast, so no lock here: we may create
// more than 1 instance, but the lock below ensures we only ever return
// 1 unique instance - and locking is a nice explicit way to ensure this

var m = new PublishedContent(this, contentData, _publishedSnapshotAccessor, _variationContextAccessor).CreateModel();

// locking 'this' is not a best-practice but ContentNode is internal and
// we know what we do, so it is fine here and avoids allocating an object
lock (this)
{
return model = model ?? m;
}
}

public IPublishedContent DraftModel => GetModel(ref _draftModel, _draftData);

public IPublishedContent PublishedModel => GetModel(ref _publishedModel, _publishedData);

public ContentNodeKit ToKit()
=> new ContentNodeKit
{
Node = this,
ContentTypeId = ContentType.Id,

DraftData = DraftContent?.ContentData,
PublishedData = PublishedContent?.ContentData
DraftData = _draftData,
PublishedData = _publishedData
};
}
}
5 changes: 2 additions & 3 deletions src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,7 @@ public override bool IsPublished(string culture = null)
// invariant content items)

// if there is no 'published' published content, no culture can be published
var hasPublished = _contentNode.PublishedContent != null;
if (!hasPublished)
if (!_contentNode.HasPublished)
return false;

// if there is a 'published' published content, and does not vary = published
Expand All @@ -247,7 +246,7 @@ public override bool IsPublished(string culture = null)

// there is a 'published' published content, and varies
// = depends on the culture
return _contentNode.PublishedContent.ContentData.CultureInfos.ContainsKey(culture);
return _contentNode.HasPublishedCulture(culture);
}

#endregion
Expand Down