From 6b3debec042eb0ec3605deb74cfae11df2db10ed Mon Sep 17 00:00:00 2001 From: nikolajlauridsen Date: Tue, 3 Dec 2024 11:05:21 +0100 Subject: [PATCH] Clear elements cache instead of refreshing it --- .../CacheRefreshingNotificationHandler.cs | 59 ++++--------------- 1 file changed, 11 insertions(+), 48 deletions(-) diff --git a/src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs b/src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs index f61968365c43..6ff5a5fe1ec9 100644 --- a/src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs +++ b/src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs @@ -45,7 +45,7 @@ public CacheRefreshingNotificationHandler( public async Task HandleAsync(ContentRefreshNotification notification, CancellationToken cancellationToken) { - await RefreshElementsCacheAsync(notification.Entity); + ClearElementsCache(); await _documentCacheService.RefreshContentAsync(notification.Entity); } @@ -54,14 +54,14 @@ public async Task HandleAsync(ContentDeletedNotification notification, Cancellat { foreach (IContent deletedEntity in notification.DeletedEntities) { - RemoveFromElementsCache(deletedEntity); + ClearElementsCache(); await _documentCacheService.DeleteItemAsync(deletedEntity); } } public async Task HandleAsync(MediaRefreshNotification notification, CancellationToken cancellationToken) { - await RefreshElementsCacheAsync(notification.Entity); + ClearElementsCache(); await _mediaCacheService.RefreshMediaAsync(notification.Entity); } @@ -69,58 +69,21 @@ public async Task HandleAsync(MediaDeletedNotification notification, Cancellatio { foreach (IMedia deletedEntity in notification.DeletedEntities) { - RemoveFromElementsCache(deletedEntity); + ClearElementsCache(); await _mediaCacheService.DeleteItemAsync(deletedEntity); } } - private async Task RefreshElementsCacheAsync(IUmbracoEntity content) + private void ClearElementsCache() { - IEnumerable parentRelations = _relationService.GetByParent(content)!; - IEnumerable childRelations = _relationService.GetByChild(content); - - var ids = parentRelations.Select(x => x.ChildId).Concat(childRelations.Select(x => x.ParentId)).ToHashSet(); - // We need to add ourselves to the list of ids to clear - ids.Add(content.Id); - foreach (var id in ids) - { - if (await _documentCacheService.HasContentByIdAsync(id) is false) - { - continue; - } - - IPublishedContent? publishedContent = await _documentCacheService.GetByIdAsync(id); - if (publishedContent is null) - { - continue; - } - - foreach (IPublishedProperty publishedProperty in publishedContent.Properties) - { - var property = (PublishedProperty) publishedProperty; - if (property.ReferenceCacheLevel is PropertyCacheLevel.Elements - || property.PropertyType.DeliveryApiCacheLevel is PropertyCacheLevel.Elements - || property.PropertyType.DeliveryApiCacheLevelForExpansion is PropertyCacheLevel.Elements) - { - _elementsCache.ClearByKey(property.ValuesCacheKey); - } - } - } + // Ideally we'd like to not have to clear the entire cache here. However, this was the existing behavior in NuCache. + // The reason for this is that we have no way to know which elements are affected by the changes. or what their keys are. + // This is because currently published elements lives exclusively in a JSON blob in the umbracoPropertyData table. + // This means that the only way to resolve these keys are to actually parse this data with a specific value converter, and for all cultures, which is not feasible. + // If published elements become their own entities with relations, instead of just property data, we can revisit this, + _elementsCache.Clear(); } - private void RemoveFromElementsCache(IUmbracoEntity content) - { - // ClearByKey clears by "startsWith" so we'll clear by the cachekey prefix + contentKey - // This will clear any and all properties for this content item, this is important because - // we cannot resolve the PublishedContent for this entity since it and its content type is deleted. - _elementsCache.ClearByKey(GetContentWideCacheKey(content.Key, true)); - _elementsCache.ClearByKey(GetContentWideCacheKey(content.Key, false)); - } - - private string GetContentWideCacheKey(Guid contentKey, bool isPreviewing) => isPreviewing - ? CacheKeys.PreviewPropertyCacheKeyPrefix + contentKey - : CacheKeys.PropertyCacheKeyPrefix + contentKey; - public Task HandleAsync(ContentTypeRefreshedNotification notification, CancellationToken cancellationToken) { const ContentTypeChangeTypes types // only for those that have been refreshed