Skip cache refresher operations for content blueprints (#15633)

* Skip cache refresher operations for content blueprints

* Fix JsonPayload deserialization error by adding a default constructor and property initializers

* Obsolete JsonPayload constructor and update usages
This commit is contained in:
Ronald Barendse
2024-02-01 09:55:09 +01:00
committed by Bjarke Berg
parent e7c53d4768
commit 25139dabe0
7 changed files with 239 additions and 50 deletions

View File

@@ -118,15 +118,35 @@ public static class DistributedCacheExtensions
#region ContentCacheRefresher
public static void RefreshAllContentCache(this DistributedCache dc)
{
ContentCacheRefresher.JsonPayload[] payloads = new[]
{
new ContentCacheRefresher.JsonPayload()
{
ChangeTypes = TreeChangeTypes.RefreshAll
}
};
// note: refresh all content cache does refresh content types too
=> dc.RefreshByPayload(ContentCacheRefresher.UniqueId, new ContentCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll).Yield());
dc.RefreshByPayload(ContentCacheRefresher.UniqueId, payloads);
}
[Obsolete("Use the overload accepting IEnumerable instead to avoid allocating arrays. This overload will be removed in Umbraco 13.")]
public static void RefreshContentCache(this DistributedCache dc, TreeChange<IContent>[] changes)
=> dc.RefreshContentCache(changes.AsEnumerable());
public static void RefreshContentCache(this DistributedCache dc, IEnumerable<TreeChange<IContent>> changes)
=> dc.RefreshByPayload(ContentCacheRefresher.UniqueId, changes.DistinctBy(x => (x.Item.Id, x.Item.Key, x.ChangeTypes)).Select(x => new ContentCacheRefresher.JsonPayload(x.Item.Id, x.Item.Key, x.ChangeTypes)));
{
IEnumerable<ContentCacheRefresher.JsonPayload> payloads = changes.Select(x => new ContentCacheRefresher.JsonPayload()
{
Id = x.Item.Id,
Key = x.Item.Key,
ChangeTypes = x.ChangeTypes,
Blueprint = x.Item.Blueprint
});
dc.RefreshByPayload(ContentCacheRefresher.UniqueId, payloads);
}
#endregion

View File

@@ -84,8 +84,8 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase<ContentCac
isolatedCache.ClearOfType<IContent>((k, v) => v.Path?.Contains(pathid) ?? false);
}
// if the item is being completely removed, we need to refresh the domains cache if any domain was assigned to the content
if (payload.ChangeTypes.HasTypesAny(TreeChangeTypes.Remove))
// if the item is not a blueprint and is being completely removed, we need to refresh the domains cache if any domain was assigned to the content
if (payload.Blueprint is false && payload.ChangeTypes.HasTypesAny(TreeChangeTypes.Remove))
{
idsRemoved.Add(payload.Id);
}
@@ -120,7 +120,11 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase<ContentCac
// should rename it, and then, this is only for Deploy, and then, ???
// if (Suspendable.PageCacheRefresher.CanUpdateDocumentCache)
// ...
NotifyPublishedSnapshotService(_publishedSnapshotService, AppCaches, payloads);
if (payloads.Any(x => x.Blueprint is false))
{
// Only notify if the payload contains actual (non-blueprint) contents
NotifyPublishedSnapshotService(_publishedSnapshotService, AppCaches, payloads);
}
base.Refresh(payloads);
}
@@ -157,8 +161,13 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase<ContentCac
}
}
// TODO (V14): Change into a record
public class JsonPayload
{
public JsonPayload()
{ }
[Obsolete("Use the default constructor and property initializers.")]
public JsonPayload(int id, Guid? key, TreeChangeTypes changeTypes)
{
Id = id;
@@ -166,11 +175,13 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase<ContentCac
ChangeTypes = changeTypes;
}
public int Id { get; }
public int Id { get; init; }
public Guid? Key { get; }
public Guid? Key { get; init; }
public TreeChangeTypes ChangeTypes { get; }
public TreeChangeTypes ChangeTypes { get; init; }
public bool Blueprint { get; init; }
}
#endregion

View File

@@ -134,8 +134,14 @@ public sealed class LanguageCacheRefresher : PayloadCacheRefresherBase<LanguageC
ContentCacheRefresher.RefreshContentTypes(AppCaches); // we need to evict all IContent items
// now refresh all nucache
ContentCacheRefresher.JsonPayload[] clearContentPayload =
new[] { new ContentCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) };
ContentCacheRefresher.JsonPayload[] clearContentPayload = new[]
{
new ContentCacheRefresher.JsonPayload()
{
ChangeTypes = TreeChangeTypes.RefreshAll
}
};
ContentCacheRefresher.NotifyPublishedSnapshotService(_publishedSnapshotService, AppCaches, clearContentPayload);
}

View File

@@ -53,13 +53,15 @@ public sealed class ContentIndexingNotificationHandler :
foreach (ContentCacheRefresher.JsonPayload payload in (ContentCacheRefresher.JsonPayload[])args.MessageObject)
{
if (payload.Blueprint)
{
// Skip blueprints
continue;
}
if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove))
{
if (deleteBatch == null)
{
deleteBatch = new HashSet<int>();
}
deleteBatch ??= new HashSet<int>();
deleteBatch.Add(payload.Id);
}
else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll))

View File

@@ -220,7 +220,16 @@ internal class PublishedSnapshotService : IPublishedSnapshotService
// they require.
using (_contentStore.GetScopedWriteLock(_scopeProvider))
{
NotifyLocked(new[] { new ContentCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) }, out _, out _);
NotifyLocked(
new[]
{
new ContentCacheRefresher.JsonPayload()
{
ChangeTypes = TreeChangeTypes.RefreshAll
}
},
out _,
out _);
}
using (_mediaStore.GetScopedWriteLock(_scopeProvider))
@@ -885,6 +894,12 @@ internal class PublishedSnapshotService : IPublishedSnapshotService
_logger.LogDebug("Notified {ChangeTypes} for content {ContentId}", payload.ChangeTypes, payload.Id);
}
if (payload.Blueprint)
{
// Skip blueprints
continue;
}
if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll))
{
using (IScope scope = _scopeProvider.CreateScope())