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

V15: Clear elements cache instead of refreshing it #17708

Merged
merged 1 commit into from
Dec 3, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

public async Task HandleAsync(ContentRefreshNotification notification, CancellationToken cancellationToken)
{
await RefreshElementsCacheAsync(notification.Entity);
ClearElementsCache();

await _documentCacheService.RefreshContentAsync(notification.Entity);
}
Expand All @@ -54,73 +54,36 @@
{
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);
}

public async Task HandleAsync(MediaDeletedNotification notification, CancellationToken cancellationToken)
{
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,

Check notice on line 83 in src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (release/15.1)

✅ No longer an issue: Complex Conditional

RefreshElementsCacheAsync no longer has a complex conditional
_elementsCache.Clear();

Check notice on line 84 in src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (release/15.1)

✅ No longer an issue: Complex Method

RefreshElementsCacheAsync is no longer above the threshold for cyclomatic complexity

Check notice on line 84 in src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (release/15.1)

✅ No longer an issue: Bumpy Road Ahead

RefreshElementsCacheAsync is no longer above the threshold for logical blocks with deeply nested code
}

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
Expand Down
Loading