diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs index e59d332525..9eec95c10f 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs @@ -647,9 +647,16 @@ namespace Umbraco.Web.PublishedCache.NuCache var id = content.FirstChildContentId; while (id > 0) { - var link = GetLinkedNode(id, "child"); - ClearBranchLocked(link.Value); - id = link.Value.NextSiblingContentId; + if (TryGetLinkedNode(id, out var link)) + { + ClearBranchLocked(link.Value); + id = link.Value.NextSiblingContentId; + } + else + { + // break i guess? + id = 0; + } } } @@ -663,6 +670,18 @@ namespace Umbraco.Web.PublishedCache.NuCache throw new Exception($"panic: failed to get {description} with id={id}"); } + private bool TryGetLinkedNode(int id, out LinkedNode node) + { + if (_contentNodes.TryGetValue(id, out var link) && link.Value != null) + { + node = link; + return true; + } + + node = null; + return false; + } + private LinkedNode GetParentLink(ContentNode content) { _contentNodes.TryGetValue(content.ParentContentId, out var link); // else null diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index 20372c074d..2e96513761 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -277,10 +277,43 @@ namespace Umbraco.Web.PublishedCache.NuCache while (id > 0) { var content = getById(publishedSnapshot, IsPreviewing, id); - if (content == null) - throw new Exception($"panic: failed to get content with id={id}"); - yield return content; + if (content != null) + { + yield return content; + } + else + { + //Why were we throwing here? It is perfectly legitimate that a child is not published and when IsPreviewing == false + //this will return null even if the item is in nucache but only with an unpublished flag. + //If we want to be very clear about something being wrong, then perhaps the exception should be thrown from within + //the Func that gets the child where it can validate if there really is nothing there when something is expected? + + //In the meantime, we cannot continue so we should break?... BUT doesn't that mean that if there was a sibling next to this that was published + //that it will now be excluded? + + //Well, in that case this is annoying, so the only thing i can think of is to get the preview version of it to get the + //next child and continue that way? + + if (IsPreviewing) + { + //if we're in preview mode and nothing is returned then something is wrong + throw new Exception($"panic: failed to get content with id={id}"); + } + else + { + //get the preview version since this item might not be published + content = getById(publishedSnapshot, true, id); + if (content == null) + { + //if we're in preview mode and nothing is returned then something is wrong + throw new Exception($"panic: failed to get content with id={id}"); + } + + //now we can continue with the next sibling id, but we aren't going to return this content item because it's not published + //and we're not previewing. + } + } id = UnwrapIPublishedContent(content)._contentNode.NextSiblingContentId; }