diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs index 884ccb0f74..5157f9493e 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs @@ -470,7 +470,7 @@ namespace Umbraco.Web.PublishedCache.NuCache private bool BuildKit(ContentNodeKit kit, out LinkedNode parent) { // make sure parent exists - parent = GetParentLink(kit.Node); + parent = GetParentLink(kit.Node, _liveGen); if (parent == null) { _logger.Warn($"Skip item id={kit.Node.Id}, could not find parent id={kit.Node.ParentContentId}."); @@ -795,7 +795,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var id = content.FirstChildContentId; while (id > 0) { - var link = GetRequiredLinkedNode(id, "child"); + var link = GetRequiredLinkedNode(id, "child", _liveGen); ClearBranchLocked(link.Value); id = link.Value.NextSiblingContentId; } @@ -807,10 +807,20 @@ namespace Umbraco.Web.PublishedCache.NuCache /// /// /// - private LinkedNode GetRequiredLinkedNode(int id, string description) + private LinkedNode GetRequiredLinkedNode(int id, string description, long gen) { - if (_contentNodes.TryGetValue(id, out var link) && link.Value != null) - return link; + if (_contentNodes.TryGetValue(id, out var link)) + { + //find the correct snapshot + while (link != null && link.Gen != gen) + { + link = link.Next; + } + + if (link.Value != null) + return link; + } + throw new PanicException($"failed to get {description} with id={id}"); } @@ -818,11 +828,27 @@ namespace Umbraco.Web.PublishedCache.NuCache /// /// Gets the parent link node, may be null or root if ParentContentId is less than 0 /// - private LinkedNode GetParentLink(ContentNode content) + private LinkedNode GetParentLink(ContentNode content, long gen) { - if (content.ParentContentId < 0) return _root; + if (content.ParentContentId < 0) + { + var root = _root; + //find the correct snapshot + while (root != null && root.Gen != gen) + { + root = root.Next; + } + return root; + } - _contentNodes.TryGetValue(content.ParentContentId, out var link); + if (_contentNodes.TryGetValue(content.ParentContentId, out var link)) + { + //find the correct snapshot + while (link != null && link.Gen != gen) + { + link = link.Next; + } + } return link; } @@ -831,16 +857,16 @@ namespace Umbraco.Web.PublishedCache.NuCache /// /// /// - private LinkedNode GetRequiredParentLink(ContentNode content) + private LinkedNode GetRequiredParentLink(ContentNode content, long gen) { - return content.ParentContentId < 0 ? _root : GetRequiredLinkedNode(content.ParentContentId, "parent"); + return content.ParentContentId < 0 ? _root : GetRequiredLinkedNode(content.ParentContentId, "parent", gen); } private void RemoveTreeNodeLocked(ContentNode content) { var parentLink = content.ParentContentId < 0 ? _root - : GetRequiredLinkedNode(content.ParentContentId, "parent"); + : GetRequiredLinkedNode(content.ParentContentId, "parent", _liveGen); var parent = parentLink.Value; @@ -863,14 +889,14 @@ namespace Umbraco.Web.PublishedCache.NuCache if (content.NextSiblingContentId > 0) { - var nextLink = GetRequiredLinkedNode(content.NextSiblingContentId, "next sibling"); + var nextLink = GetRequiredLinkedNode(content.NextSiblingContentId, "next sibling", _liveGen); var next = GenCloneLocked(nextLink); next.PreviousSiblingContentId = content.PreviousSiblingContentId; } if (content.PreviousSiblingContentId > 0) { - var prevLink = GetRequiredLinkedNode(content.PreviousSiblingContentId, "previous sibling"); + var prevLink = GetRequiredLinkedNode(content.PreviousSiblingContentId, "previous sibling", _liveGen); var prev = GenCloneLocked(prevLink); prev.NextSiblingContentId = content.NextSiblingContentId; } @@ -883,7 +909,7 @@ namespace Umbraco.Web.PublishedCache.NuCache { if (kit.Node.ParentContentId < 0) return true; - var link = GetParentLink(kit.Node); + var link = GetParentLink(kit.Node, _liveGen); var node = link?.Value; return node != null && node.HasPublished; } @@ -909,10 +935,12 @@ namespace Umbraco.Web.PublishedCache.NuCache /// private void AddTreeNodeLocked(ContentNode content, LinkedNode parentLink = null) { - parentLink = parentLink ?? GetRequiredParentLink(content); + parentLink = parentLink ?? GetRequiredParentLink(content, _liveGen); var parent = parentLink.Value; + var currentGen = parentLink.Gen; + // if parent has no children, clone parent + add as first child if (parent.FirstChildContentId < 0) { @@ -923,7 +951,7 @@ namespace Umbraco.Web.PublishedCache.NuCache } // get parent's first child - var childLink = GetRequiredLinkedNode(parent.FirstChildContentId, "first child"); + var childLink = GetRequiredLinkedNode(parent.FirstChildContentId, "first child", currentGen); var child = childLink.Value; // if first, clone parent + insert as first child @@ -943,7 +971,7 @@ namespace Umbraco.Web.PublishedCache.NuCache } // get parent's last child - var lastChildLink = GetRequiredLinkedNode(parent.LastChildContentId, "last child"); + var lastChildLink = GetRequiredLinkedNode(parent.LastChildContentId, "last child", currentGen); var lastChild = lastChildLink.Value; // if last, clone parent + append as last child @@ -968,7 +996,7 @@ namespace Umbraco.Web.PublishedCache.NuCache while (child.NextSiblingContentId > 0) { // get next child - var nextChildLink = GetRequiredLinkedNode(child.NextSiblingContentId, "next child"); + var nextChildLink = GetRequiredLinkedNode(child.NextSiblingContentId, "next child", currentGen); var nextChild = nextChildLink.Value; // if here, clone previous + append/insert @@ -1086,7 +1114,7 @@ namespace Umbraco.Web.PublishedCache.NuCache while (id > 0) { - var link = GetRequiredLinkedNode(id, "sibling"); + var link = GetRequiredLinkedNode(id, "root", gen); yield return link.Value; id = link.Value.NextSiblingContentId; }