You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
7.9 KiB
C#

using NPin.Framework.SettingManagement.Domain.Caching;
using NPin.Framework.SettingManagement.Domain.Entities;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
namespace NPin.Framework.SettingManagement.Domain.Store;
public class SettingManagementStore : ISettingManagementStore, ITransientDependency
{
protected IDistributedCache<SettingCacheItem> Cache { get; }
protected ISettingDefinitionManager SettingDefinitionManager { get; }
protected ISettingRepository SettingRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
public SettingManagementStore(IDistributedCache<SettingCacheItem> cache,
ISettingDefinitionManager settingDefinitionManager, ISettingRepository settingRepository,
IGuidGenerator guidGenerator)
{
Cache = cache;
SettingDefinitionManager = settingDefinitionManager;
SettingRepository = settingRepository;
GuidGenerator = guidGenerator;
}
[UnitOfWork]
public virtual async Task<string?> GetOrNullAsync(string name, string providerName, string providerKey)
{
return (await GetCacheItemAsync(name, providerName, providerKey)).Value;
}
[UnitOfWork]
public virtual async Task<List<SettingValue>> GetListAsync(string providerName, string providerKey)
{
var settings = await SettingRepository.GetListAsync(providerName, providerKey);
return settings.Select(s => new SettingValue(s.Name, s.Value)).ToList();
}
[UnitOfWork]
public virtual async Task<List<SettingValue>> GetListAsync(string[] names, string providerName, string providerKey)
{
Check.NotNullOrEmpty(names, nameof(names));
var result = new List<SettingValue>();
if (names.Length == 1)
{
var name = names.First();
result.Add(new SettingValue(name, (await GetCacheItemAsync(name, providerName, providerKey)).Value));
return result;
}
var cacheItems = await GetCacheItemsAsync(names, providerName, providerKey);
result.AddRange(cacheItems.Select(item =>
new SettingValue(GetSettingNameFormCacheKeyOrNull(item.Key), item.Value?.Value)));
return result;
}
[UnitOfWork]
public virtual async Task SetAsync(string name, string value, string providerName, string providerKey)
{
var setting = await SettingRepository.FindAsync(name, providerName, providerKey);
if (setting == null)
{
setting = new SettingEntity(GuidGenerator.Create(), name, value, providerName, providerKey);
await SettingRepository.InsertAsync(setting);
}
else
{
setting.Value = value;
await SettingRepository.UpdateAsync(setting);
}
await Cache.SetAsync(CalculateCacheKey(name, providerName, providerKey), new SettingCacheItem(setting.Value),
considerUow: true);
}
[UnitOfWork]
public virtual async Task DeleteAsync(string name, string providerName, string providerKey)
{
var setting = await SettingRepository.FindAsync(name, providerName, providerKey);
if (setting != null)
{
await SettingRepository.DeleteAsync(setting);
await Cache.RemoveAsync(CalculateCacheKey(name, providerName, providerKey), considerUow: true);
}
}
protected virtual async Task<SettingCacheItem> GetCacheItemAsync(string name, string providerName,
string providerKey)
{
var cacheKey = CalculateCacheKey(name, providerName, providerKey);
var cacheItem = await Cache.GetAsync(cacheKey, considerUow: true);
if (cacheItem != null)
{
return cacheItem;
}
cacheItem = new SettingCacheItem(null);
await SetCacheItemsAsync(providerName, providerKey, name, cacheItem);
return cacheItem;
}
protected virtual async Task<List<KeyValuePair<string, SettingCacheItem>>> GetCacheItemsAsync(string[] names,
string providerName, string providerKey)
{
var cacheKeys = names.Select(x => CalculateCacheKey(x, providerName, providerKey)).ToList();
var cacheItems = (await Cache.GetManyAsync(cacheKeys, considerUow: true)).ToList();
if (cacheItems.All(x => x.Value != null))
{
return cacheItems;
}
var notCacheKeys = cacheItems.Where(x => x.Value == null).Select(x => x.Key).ToList();
var newCacheItems = await SetCacheItemsAsync(providerName, providerKey, notCacheKeys);
var result = new List<KeyValuePair<string, SettingCacheItem>>();
foreach (var key in cacheKeys)
{
var item = newCacheItems.FirstOrDefault(x => x.Key == key);
if (item.Value == null)
{
item = cacheItems.FirstOrDefault(x => x.Key == key);
}
result.Add(new KeyValuePair<string, SettingCacheItem>(key, item.Value));
}
return result;
}
private async Task SetCacheItemsAsync(
string providerName,
string providerKey,
string currentName,
SettingCacheItem currentCacheItem)
{
var settingDefinitions = await SettingDefinitionManager.GetAllAsync();
var settingsDictionary = (await SettingRepository.GetListAsync(providerName, providerKey))
.ToDictionary(s => s.Name, s => s.Value);
var cacheItems = new List<KeyValuePair<string, SettingCacheItem>>();
foreach (var settingDefinition in settingDefinitions)
{
var settingValue = settingsDictionary.GetOrDefault(settingDefinition.Name);
cacheItems.Add(
new KeyValuePair<string, SettingCacheItem>(
CalculateCacheKey(settingDefinition.Name, providerName, providerKey),
new SettingCacheItem(settingValue)
)
);
if (settingDefinition.Name == currentName)
{
currentCacheItem.Value = settingValue;
}
}
await Cache.SetManyAsync(cacheItems, considerUow: true);
}
private async Task<List<KeyValuePair<string, SettingCacheItem>>> SetCacheItemsAsync(
string providerName,
string providerKey,
List<string> notCacheKeys)
{
var settingDefinitions = (await SettingDefinitionManager.GetAllAsync()).Where(x =>
notCacheKeys.Any(k => GetSettingNameFormCacheKeyOrNull(k) == x.Name));
var settingsDictionary =
(await SettingRepository.GetListAsync(notCacheKeys.Select(GetSettingNameFormCacheKeyOrNull).ToArray(),
providerName, providerKey))
.ToDictionary(s => s.Name, s => s.Value);
var cacheItems = new List<KeyValuePair<string, SettingCacheItem>>();
foreach (var settingDefinition in settingDefinitions)
{
var settingValue = settingsDictionary.GetOrDefault(settingDefinition.Name);
cacheItems.Add(
new KeyValuePair<string, SettingCacheItem>(
CalculateCacheKey(settingDefinition.Name, providerName, providerKey),
new SettingCacheItem(settingValue)
)
);
}
await Cache.SetManyAsync(cacheItems, considerUow: true);
return cacheItems;
}
protected virtual string CalculateCacheKey(string name, string providerName, string providerKey)
{
return SettingCacheItem.CalculateCacheKey(name, providerName, providerKey);
}
protected virtual string? GetSettingNameFormCacheKeyOrNull(string key)
{
//TODO: throw ex when name is null?
return SettingCacheItem.GetSettingNameFormCacheKeyOrNull(key);
}
}