From 8fe8e75fa8c5e8fff19a0b4f0bf451d0aad3c612 Mon Sep 17 00:00:00 2001 From: kjac Date: Mon, 20 Nov 2023 19:52:36 +0100 Subject: [PATCH 1/4] Cache block item constructors for block based editors --- .../UmbracoBuilder.CoreServices.cs | 3 +++ ...EditorPropertyValueConstructorCacheBase.cs | 19 +++++++++++++++++++ .../BlockGridPropertyValueConstructorCache.cs | 7 +++++++ .../BlockGridPropertyValueConverter.cs | 17 +++++++++++++++-- .../BlockGridPropertyValueCreator.cs | 13 +++++++++---- .../BlockListPropertyValueConstructorCache.cs | 7 +++++++ .../BlockListPropertyValueConverter.cs | 10 +++++++++- .../BlockListPropertyValueCreator.cs | 14 ++++++++------ .../BlockPropertyValueCreatorBase.cs | 16 +++++++++------- ...hTextBlockPropertyValueConstructorCache.cs | 7 +++++++ .../RichTextBlockPropertyValueCreator.cs | 12 +++++++----- .../RteMacroRenderingValueConverter.cs | 7 +++++-- 12 files changed, 105 insertions(+), 27 deletions(-) create mode 100644 src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockEditorPropertyValueConstructorCacheBase.cs create mode 100644 src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConstructorCache.cs create mode 100644 src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueConstructorCache.cs create mode 100644 src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RichTextBlockPropertyValueConstructorCache.cs diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs index 1dff6e7eebc6..5881c177ae93 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs @@ -162,6 +162,9 @@ public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builde builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be // discovered when CoreBootManager configures the converters. We will remove the basic one defined diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockEditorPropertyValueConstructorCacheBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockEditorPropertyValueConstructorCacheBase.cs new file mode 100644 index 000000000000..f7a1b9c884f5 --- /dev/null +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockEditorPropertyValueConstructorCacheBase.cs @@ -0,0 +1,19 @@ +using System.Diagnostics.CodeAnalysis; +using Umbraco.Cms.Core.Models.Blocks; +using Umbraco.Cms.Core.Models.PublishedContent; + +namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; + +public abstract class BlockEditorPropertyValueConstructorCacheBase + where T : IBlockReference +{ + private readonly + Dictionary<(Guid, Guid?), Func> + _constructorCache = new(); + + public bool TryGetValue((Guid ContentTypeKey, Guid? SettingsTypeKey) key, [MaybeNullWhen(false)] out Func value) + => _constructorCache.TryGetValue(key, out value); + + public void SetValue((Guid ContentTypeKey, Guid? SettingsTypeKey) key, Func value) + => _constructorCache[key] = value; +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConstructorCache.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConstructorCache.cs new file mode 100644 index 000000000000..61543810131a --- /dev/null +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConstructorCache.cs @@ -0,0 +1,7 @@ +using Umbraco.Cms.Core.Models.Blocks; + +namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; + +public class BlockGridPropertyValueConstructorCache : BlockEditorPropertyValueConstructorCacheBase +{ +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConverter.cs index d0e1e2ba1976..6ca6c30b3c47 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConverter.cs @@ -21,8 +21,9 @@ public class BlockGridPropertyValueConverter : PropertyValueConverterBase, IDeli private readonly BlockEditorConverter _blockConverter; private readonly IJsonSerializer _jsonSerializer; private readonly IApiElementBuilder _apiElementBuilder; + private readonly BlockGridPropertyValueConstructorCache _constructorCache; - [Obsolete("Please use non-obsolete cconstrutor. This will be removed in Umbraco 14.")] + [Obsolete("Please use non-obsolete construtor. This will be removed in Umbraco 14.")] public BlockGridPropertyValueConverter( IProfilingLogger proflog, BlockEditorConverter blockConverter, @@ -32,16 +33,28 @@ public BlockGridPropertyValueConverter( } + [Obsolete("Please use non-obsolete construtor. This will be removed in Umbraco 15.")] public BlockGridPropertyValueConverter( IProfilingLogger proflog, BlockEditorConverter blockConverter, IJsonSerializer jsonSerializer, IApiElementBuilder apiElementBuilder) + : this(proflog, blockConverter, jsonSerializer, apiElementBuilder, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public BlockGridPropertyValueConverter( + IProfilingLogger proflog, + BlockEditorConverter blockConverter, + IJsonSerializer jsonSerializer, + IApiElementBuilder apiElementBuilder, + BlockGridPropertyValueConstructorCache constructorCache) { _proflog = proflog; _blockConverter = blockConverter; _jsonSerializer = jsonSerializer; _apiElementBuilder = apiElementBuilder; + _constructorCache = constructorCache; } /// @@ -129,7 +142,7 @@ ApiBlockGridArea CreateApiBlockGridArea(BlockGridArea area) return null; } - var creator = new BlockGridPropertyValueCreator(_blockConverter, _jsonSerializer); + var creator = new BlockGridPropertyValueCreator(_blockConverter, _jsonSerializer, _constructorCache); return creator.CreateBlockModel(referenceCacheLevel, intermediateBlockModelValue, preview, configuration.Blocks, configuration.GridColumns); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueCreator.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueCreator.cs index b50d95f5c304..9c7d7418fb03 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueCreator.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueCreator.cs @@ -7,10 +7,14 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; internal class BlockGridPropertyValueCreator : BlockPropertyValueCreatorBase { private readonly IJsonSerializer _jsonSerializer; + private readonly BlockGridPropertyValueConstructorCache _constructorCache; - public BlockGridPropertyValueCreator(BlockEditorConverter blockEditorConverter, IJsonSerializer jsonSerializer) + public BlockGridPropertyValueCreator(BlockEditorConverter blockEditorConverter, IJsonSerializer jsonSerializer, BlockGridPropertyValueConstructorCache constructorCache) : base(blockEditorConverter) - => _jsonSerializer = jsonSerializer; + { + _jsonSerializer = jsonSerializer; + _constructorCache = constructorCache; + } public BlockGridModel CreateBlockModel(PropertyCacheLevel referenceCacheLevel, string intermediateBlockModelValue, bool preview, BlockGridConfiguration.BlockGridBlockConfiguration[] blockConfigurations, int? gridColumns) { @@ -55,11 +59,12 @@ public BlockGridModel CreateBlockModel(PropertyCacheLevel referenceCacheLevel, s protected override BlockEditorDataConverter CreateBlockEditorDataConverter() => new BlockGridEditorDataConverter(_jsonSerializer); - protected override BlockItemActivator CreateBlockItemActivator() => new BlockGridItemActivator(BlockEditorConverter); + protected override BlockItemActivator CreateBlockItemActivator() => new BlockGridItemActivator(BlockEditorConverter, _constructorCache); private class BlockGridItemActivator : BlockItemActivator { - public BlockGridItemActivator(BlockEditorConverter blockConverter) : base(blockConverter) + public BlockGridItemActivator(BlockEditorConverter blockConverter, BlockGridPropertyValueConstructorCache constructorCache) + : base(blockConverter, constructorCache) { } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueConstructorCache.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueConstructorCache.cs new file mode 100644 index 000000000000..b07185a9544e --- /dev/null +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueConstructorCache.cs @@ -0,0 +1,7 @@ +using Umbraco.Cms.Core.Models.Blocks; + +namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; + +public class BlockListPropertyValueConstructorCache : BlockEditorPropertyValueConstructorCacheBase +{ +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueConverter.cs index 03445094c14a..49562b07a00f 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueConverter.cs @@ -23,6 +23,7 @@ public class BlockListPropertyValueConverter : PropertyValueConverterBase, IDeli private readonly IProfilingLogger _proflog; private readonly BlockEditorConverter _blockConverter; private readonly IApiElementBuilder _apiElementBuilder; + private readonly BlockListPropertyValueConstructorCache _constructorCache; [Obsolete("Use the constructor that takes all parameters, scheduled for removal in V14")] public BlockListPropertyValueConverter(IProfilingLogger proflog, BlockEditorConverter blockConverter) @@ -36,12 +37,19 @@ public BlockListPropertyValueConverter(IProfilingLogger proflog, BlockEditorConv { } + [Obsolete("Use the constructor that takes all parameters, scheduled for removal in V15")] public BlockListPropertyValueConverter(IProfilingLogger proflog, BlockEditorConverter blockConverter, IContentTypeService contentTypeService, IApiElementBuilder apiElementBuilder) + : this(proflog, blockConverter, contentTypeService, apiElementBuilder, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public BlockListPropertyValueConverter(IProfilingLogger proflog, BlockEditorConverter blockConverter, IContentTypeService contentTypeService, IApiElementBuilder apiElementBuilder, BlockListPropertyValueConstructorCache constructorCache) { _proflog = proflog; _blockConverter = blockConverter; _contentTypeService = contentTypeService; _apiElementBuilder = apiElementBuilder; + _constructorCache = constructorCache; } /// @@ -153,7 +161,7 @@ public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) return null; } - var creator = new BlockListPropertyValueCreator(_blockConverter); + var creator = new BlockListPropertyValueCreator(_blockConverter, _constructorCache); return creator.CreateBlockModel(referenceCacheLevel, intermediateBlockModelValue, preview, configuration.Blocks); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueCreator.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueCreator.cs index 952dc43e2ffd..daa390241ca0 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueCreator.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockListPropertyValueCreator.cs @@ -4,10 +4,11 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; internal class BlockListPropertyValueCreator : BlockPropertyValueCreatorBase { - public BlockListPropertyValueCreator(BlockEditorConverter blockEditorConverter) - : base(blockEditorConverter) - { - } + private readonly BlockListPropertyValueConstructorCache _constructorCache; + + public BlockListPropertyValueCreator(BlockEditorConverter blockEditorConverter, BlockListPropertyValueConstructorCache constructorCache) + : base(blockEditorConverter) => + _constructorCache = constructorCache; public BlockListModel CreateBlockModel(PropertyCacheLevel referenceCacheLevel, string intermediateBlockModelValue, bool preview, BlockListConfiguration.BlockConfiguration[] blockConfigurations) { @@ -22,11 +23,12 @@ public BlockListModel CreateBlockModel(PropertyCacheLevel referenceCacheLevel, s protected override BlockEditorDataConverter CreateBlockEditorDataConverter() => new BlockListEditorDataConverter(); - protected override BlockItemActivator CreateBlockItemActivator() => new BlockListItemActivator(BlockEditorConverter); + protected override BlockItemActivator CreateBlockItemActivator() => new BlockListItemActivator(BlockEditorConverter, _constructorCache); private class BlockListItemActivator : BlockItemActivator { - public BlockListItemActivator(BlockEditorConverter blockConverter) : base(blockConverter) + public BlockListItemActivator(BlockEditorConverter blockConverter, BlockListPropertyValueConstructorCache constructorCache) + : base(blockConverter, constructorCache) { } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockPropertyValueCreatorBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockPropertyValueCreatorBase.cs index 84a82338db3e..ef5195808260 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockPropertyValueCreatorBase.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockPropertyValueCreatorBase.cs @@ -216,17 +216,19 @@ private TBlockModel CreateBlockModel( // Cache constructors locally (it's tied to the current IPublishedSnapshot and IPublishedModelFactory) protected abstract class BlockItemActivator + where T : IBlockReference { protected abstract Type GenericItemType { get; } private readonly BlockEditorConverter _blockConverter; - private readonly - Dictionary<(Guid, Guid?), Func> - _constructorCache = new(); + private readonly BlockEditorPropertyValueConstructorCacheBase _constructorCache; - public BlockItemActivator(BlockEditorConverter blockConverter) - => _blockConverter = blockConverter; + public BlockItemActivator(BlockEditorConverter blockConverter, BlockEditorPropertyValueConstructorCacheBase constructorCache) + { + _blockConverter = blockConverter; + _constructorCache = constructorCache; + } public T CreateInstance(Guid contentTypeKey, Guid? settingsTypeKey, Udi contentUdi, IPublishedElement contentData, Udi? settingsUdi, IPublishedElement? settingsData) { @@ -234,8 +236,8 @@ public T CreateInstance(Guid contentTypeKey, Guid? settingsTypeKey, Udi contentU (contentTypeKey, settingsTypeKey), out Func? constructor)) { - constructor = _constructorCache[(contentTypeKey, settingsTypeKey)] = - EmitConstructor(contentTypeKey, settingsTypeKey); + constructor = EmitConstructor(contentTypeKey, settingsTypeKey); + _constructorCache.SetValue((contentTypeKey, settingsTypeKey), constructor); } return constructor(contentUdi, contentData, settingsUdi, settingsData); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RichTextBlockPropertyValueConstructorCache.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RichTextBlockPropertyValueConstructorCache.cs new file mode 100644 index 000000000000..f6458df23ff1 --- /dev/null +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RichTextBlockPropertyValueConstructorCache.cs @@ -0,0 +1,7 @@ +using Umbraco.Cms.Core.Models.Blocks; + +namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; + +public class RichTextBlockPropertyValueConstructorCache : BlockEditorPropertyValueConstructorCacheBase +{ +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RichTextBlockPropertyValueCreator.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RichTextBlockPropertyValueCreator.cs index b4ff9510f1ad..4616f0342585 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RichTextBlockPropertyValueCreator.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RichTextBlockPropertyValueCreator.cs @@ -7,10 +7,11 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; internal class RichTextBlockPropertyValueCreator : BlockPropertyValueCreatorBase { - public RichTextBlockPropertyValueCreator(BlockEditorConverter blockEditorConverter) + private readonly RichTextBlockPropertyValueConstructorCache _constructorCache; + + public RichTextBlockPropertyValueCreator(BlockEditorConverter blockEditorConverter, RichTextBlockPropertyValueConstructorCache constructorCache) : base(blockEditorConverter) - { - } + => _constructorCache = constructorCache; public RichTextBlockModel CreateBlockModel(PropertyCacheLevel referenceCacheLevel, BlockValue blockValue, bool preview, RichTextConfiguration.RichTextBlockConfiguration[] blockConfigurations) { @@ -25,11 +26,12 @@ public RichTextBlockModel CreateBlockModel(PropertyCacheLevel referenceCacheLeve protected override BlockEditorDataConverter CreateBlockEditorDataConverter() => new RichTextEditorBlockDataConverter(); - protected override BlockItemActivator CreateBlockItemActivator() => new RichTextBlockItemActivator(BlockEditorConverter); + protected override BlockItemActivator CreateBlockItemActivator() => new RichTextBlockItemActivator(BlockEditorConverter, _constructorCache); private class RichTextBlockItemActivator : BlockItemActivator { - public RichTextBlockItemActivator(BlockEditorConverter blockConverter) : base(blockConverter) + public RichTextBlockItemActivator(BlockEditorConverter blockConverter, RichTextBlockPropertyValueConstructorCache constructorCache) + : base(blockConverter, constructorCache) { } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs index 871595b3bc2b..06ec417c4cd9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs @@ -46,6 +46,7 @@ public class RteMacroRenderingValueConverter : SimpleTinyMceValueConverter, IDel private readonly IJsonSerializer _jsonSerializer; private readonly ILogger _logger; private readonly IApiElementBuilder _apiElementBuilder; + private readonly RichTextBlockPropertyValueConstructorCache _constructorCache; private DeliveryApiSettings _deliveryApiSettings; [Obsolete("Please use the constructor that takes all arguments. Will be removed in V14.")] @@ -79,6 +80,7 @@ public RteMacroRenderingValueConverter(IUmbracoContextAccessor umbracoContextAcc StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService>(), deliveryApiSettingsMonitor ) @@ -89,7 +91,7 @@ public RteMacroRenderingValueConverter(IUmbracoContextAccessor umbracoContextAcc HtmlLocalLinkParser linkParser, HtmlUrlParser urlParser, HtmlImageSourceParser imageSourceParser, IApiRichTextElementParser apiRichTextElementParser, IApiRichTextMarkupParser apiRichTextMarkupParser, IPartialViewBlockEngine partialViewBlockEngine, BlockEditorConverter blockEditorConverter, IJsonSerializer jsonSerializer, - IApiElementBuilder apiElementBuilder, ILogger logger, + IApiElementBuilder apiElementBuilder, RichTextBlockPropertyValueConstructorCache constructorCache, ILogger logger, IOptionsMonitor deliveryApiSettingsMonitor) { _umbracoContextAccessor = umbracoContextAccessor; @@ -103,6 +105,7 @@ public RteMacroRenderingValueConverter(IUmbracoContextAccessor umbracoContextAcc _blockEditorConverter = blockEditorConverter; _jsonSerializer = jsonSerializer; _apiElementBuilder = apiElementBuilder; + _constructorCache = constructorCache; _logger = logger; _deliveryApiSettings = deliveryApiSettingsMonitor.CurrentValue; deliveryApiSettingsMonitor.OnChange(settings => _deliveryApiSettings = settings); @@ -267,7 +270,7 @@ private string RenderRteMacros(string source, bool preview) return null; } - var creator = new RichTextBlockPropertyValueCreator(_blockEditorConverter); + var creator = new RichTextBlockPropertyValueCreator(_blockEditorConverter, _constructorCache); return creator.CreateBlockModel(referenceCacheLevel, blocks, preview, configuration.Blocks); } From ac8574ea390ce04d4de2bc28f348751e2003fbcd Mon Sep 17 00:00:00 2001 From: kjac Date: Tue, 21 Nov 2023 07:18:31 +0100 Subject: [PATCH 2/4] Fix unit tests --- .../PropertyEditors/BlockListPropertyValueConverterTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/BlockListPropertyValueConverterTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/BlockListPropertyValueConverterTests.cs index f0971ffee6cd..423231eeeed8 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/BlockListPropertyValueConverterTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/BlockListPropertyValueConverterTests.cs @@ -27,7 +27,8 @@ private BlockListPropertyValueConverter CreateConverter() Mock.Of(), new BlockEditorConverter(publishedSnapshotAccessor, publishedModelFactory), Mock.Of(), - new ApiElementBuilder(Mock.Of())); + new ApiElementBuilder(Mock.Of()), + new BlockListPropertyValueConstructorCache()); return editor; } From 0d8e8bb20cb40c2b0e6fd7246c095767bb6a4738 Mon Sep 17 00:00:00 2001 From: kjac Date: Tue, 21 Nov 2023 09:08:05 +0100 Subject: [PATCH 3/4] Fixed Grid unit tests --- .../PropertyEditors/BlockGridPropertyValueConverterTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/BlockGridPropertyValueConverterTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/BlockGridPropertyValueConverterTests.cs index 89379322ee96..2d65ff50933d 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/BlockGridPropertyValueConverterTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/BlockGridPropertyValueConverterTests.cs @@ -37,7 +37,8 @@ private BlockGridPropertyValueConverter CreateConverter() Mock.Of(), new BlockEditorConverter(publishedSnapshotAccessor, publishedModelFactory), new JsonNetSerializer(), - new ApiElementBuilder(Mock.Of())); + new ApiElementBuilder(Mock.Of()), + new BlockGridPropertyValueConstructorCache()); return editor; } From 5a02dffa6e46e4a77167787747f8c39638a767e7 Mon Sep 17 00:00:00 2001 From: kjac Date: Tue, 28 Nov 2023 14:18:29 +0100 Subject: [PATCH 4/4] Clear constructor caches when content types and data types change (to support InMemoryAuto models) --- .../UmbracoBuilder.CoreServices.cs | 4 +- ...EditorPropertyValueConstructorCacheBase.cs | 3 ++ ...onstructorCacheClearNotificationHandler.cs | 38 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/ConstructorCacheClearNotificationHandler.cs diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs index 5881c177ae93..754c0e349eea 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs @@ -370,7 +370,9 @@ public static IUmbracoBuilder AddCoreNotifications(this IUmbracoBuilder builder) .AddNotificationHandler() .AddNotificationHandler() .AddNotificationHandler() - .AddNotificationHandler(); + .AddNotificationHandler() + .AddNotificationHandler() + .AddNotificationHandler(); // add notification handlers for redirect tracking builder diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockEditorPropertyValueConstructorCacheBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockEditorPropertyValueConstructorCacheBase.cs index f7a1b9c884f5..3edd1a680ee8 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockEditorPropertyValueConstructorCacheBase.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockEditorPropertyValueConstructorCacheBase.cs @@ -16,4 +16,7 @@ public bool TryGetValue((Guid ContentTypeKey, Guid? SettingsTypeKey) key, [Maybe public void SetValue((Guid ContentTypeKey, Guid? SettingsTypeKey) key, Func value) => _constructorCache[key] = value; + + public void Clear() + => _constructorCache.Clear(); } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/ConstructorCacheClearNotificationHandler.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/ConstructorCacheClearNotificationHandler.cs new file mode 100644 index 000000000000..2abbfe73e0be --- /dev/null +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/ConstructorCacheClearNotificationHandler.cs @@ -0,0 +1,38 @@ +using Umbraco.Cms.Core.Events; +using Umbraco.Cms.Core.Notifications; + +namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; + +public class ConstructorCacheClearNotificationHandler : + INotificationHandler, + INotificationHandler +{ + private readonly BlockListPropertyValueConstructorCache _blockListPropertyValueConstructorCache; + private readonly BlockGridPropertyValueConstructorCache _blockGridPropertyValueConstructorCache; + private readonly RichTextBlockPropertyValueConstructorCache _richTextBlockPropertyValueConstructorCache; + + public ConstructorCacheClearNotificationHandler( + BlockListPropertyValueConstructorCache blockListPropertyValueConstructorCache, + BlockGridPropertyValueConstructorCache blockGridPropertyValueConstructorCache, + RichTextBlockPropertyValueConstructorCache richTextBlockPropertyValueConstructorCache) + { + _blockListPropertyValueConstructorCache = blockListPropertyValueConstructorCache; + _blockGridPropertyValueConstructorCache = blockGridPropertyValueConstructorCache; + _richTextBlockPropertyValueConstructorCache = richTextBlockPropertyValueConstructorCache; + } + + public void Handle(ContentTypeCacheRefresherNotification notification) + => ClearCaches(); + + public void Handle(DataTypeCacheRefresherNotification notification) + => ClearCaches(); + + private void ClearCaches() + { + // must clear the block item constructor caches whenever content types and data types change, + // otherwise InMemoryAuto generated models will not work. + _blockListPropertyValueConstructorCache.Clear(); + _blockGridPropertyValueConstructorCache.Clear(); + _richTextBlockPropertyValueConstructorCache.Clear(); + } +}