Merge pull request #10946 from umbraco/v9/feature/validationService-optimization

V9: Reuse value editors for validation
This commit is contained in:
Nikolaj Geisle
2021-08-31 13:58:01 +02:00
committed by GitHub
11 changed files with 302 additions and 5 deletions

View File

@@ -0,0 +1,12 @@
using System.Collections.Generic;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors;
namespace Umbraco.Cms.Core.Cache
{
public interface IValueEditorCache
{
public IDataValueEditor GetValueEditor(IDataEditor dataEditor, IDataType dataType);
public void ClearCache(IEnumerable<int> dataTypeIds);
}
}

View File

@@ -0,0 +1,61 @@
using System.Collections.Generic;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors;
namespace Umbraco.Cms.Core.Cache
{
public class ValueEditorCache : IValueEditorCache
{
private readonly Dictionary<string, Dictionary<int, IDataValueEditor>> _valueEditorCache;
private readonly object _dictionaryLocker;
public ValueEditorCache()
{
_valueEditorCache = new Dictionary<string, Dictionary<int, IDataValueEditor>>();
_dictionaryLocker = new object();
}
public IDataValueEditor GetValueEditor(IDataEditor editor, IDataType dataType)
{
// Lock just in case multiple threads uses the cache at the same time.
lock (_dictionaryLocker)
{
// We try and get the dictionary based on the IDataEditor alias,
// this is here just in case a data type can have more than one value data editor.
// If this is not the case this could be simplified quite a bit, by just using the inner dictionary only.
IDataValueEditor valueEditor;
if (_valueEditorCache.TryGetValue(editor.Alias, out Dictionary<int, IDataValueEditor> dataEditorCache))
{
if (dataEditorCache.TryGetValue(dataType.Id, out valueEditor))
{
return valueEditor;
}
valueEditor = editor.GetValueEditor(dataType.Configuration);
dataEditorCache[dataType.Id] = valueEditor;
return valueEditor;
}
valueEditor = editor.GetValueEditor(dataType.Configuration);
_valueEditorCache[editor.Alias] = new Dictionary<int, IDataValueEditor> { [dataType.Id] = valueEditor };
return valueEditor;
}
}
public void ClearCache(IEnumerable<int> dataTypeIds)
{
lock (_dictionaryLocker)
{
// If a datatype is saved or deleted we have to clear any value editors based on their ID from the cache,
// since it could mean that their configuration has changed.
foreach (var id in dataTypeIds)
{
foreach (Dictionary<int, IDataValueEditor> editors in _valueEditorCache.Values)
{
editors.Remove(id);
}
}
}
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Serialization;
namespace Umbraco.Cms.Core.Cache
{
public sealed class ValueEditorCacheRefresher : PayloadCacheRefresherBase<DataTypeCacheRefresherNotification, DataTypeCacheRefresher.JsonPayload>
{
private readonly IValueEditorCache _valueEditorCache;
public ValueEditorCacheRefresher(
AppCaches appCaches,
IJsonSerializer serializer,
IEventAggregator eventAggregator,
ICacheRefresherNotificationFactory factory,
IValueEditorCache valueEditorCache) : base(appCaches, serializer, eventAggregator, factory)
{
_valueEditorCache = valueEditorCache;
}
public static readonly Guid UniqueId = Guid.Parse("D28A1DBB-2308-4918-9A92-2F8689B6CBFE");
public override Guid RefresherUniqueId => UniqueId;
public override string Name => "ValueEditorCacheRefresher";
public override void Refresh(DataTypeCacheRefresher.JsonPayload[] payloads)
{
IEnumerable<int> ids = payloads.Select(x => x.Id);
_valueEditorCache.ClearCache(ids);
}
// these events should never trigger
// everything should be PAYLOAD/JSON
public override void RefreshAll()
{
throw new NotSupportedException();
}
public override void Refresh(int id)
{
throw new NotSupportedException();
}
public override void Refresh(Guid id)
{
throw new NotSupportedException();
}
public override void Remove(int id)
{
throw new NotSupportedException();
}
}
}

View File

@@ -253,6 +253,9 @@ namespace Umbraco.Cms.Core.DependencyInjection
// register a basic/noop published snapshot service to be replaced
Services.AddSingleton<IPublishedSnapshotService, InternalPublishedSnapshotService>();
// Register ValueEditorCache used for validation
Services.AddSingleton<IValueEditorCache, ValueEditorCache>();
}
}
}