Clear elements cache instead of refreshing it (#17708)

This commit is contained in:
Mole
2024-12-03 13:40:05 +01:00
committed by GitHub
parent 437fcba4e5
commit 380f3f7e87

View File

@@ -45,7 +45,7 @@ internal sealed class CacheRefreshingNotificationHandler :
public async Task HandleAsync(ContentRefreshNotification notification, CancellationToken cancellationToken)
{
await RefreshElementsCacheAsync(notification.Entity);
ClearElementsCache();
await _documentCacheService.RefreshContentAsync(notification.Entity);
}
@@ -54,14 +54,14 @@ internal sealed class CacheRefreshingNotificationHandler :
{
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 @@ internal sealed class CacheRefreshingNotificationHandler :
{
foreach (IMedia deletedEntity in notification.DeletedEntities)
{
RemoveFromElementsCache(deletedEntity);
ClearElementsCache();
await _mediaCacheService.DeleteItemAsync(deletedEntity);
}
}
private async Task RefreshElementsCacheAsync(IUmbracoEntity content)
private void ClearElementsCache()
{
IEnumerable<IRelation> parentRelations = _relationService.GetByParent(content)!;
IEnumerable<IRelation> 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