Small groundwork done, switching to another task due to blocker
This commit is contained in:
@@ -12,7 +12,7 @@ public interface ILanguageRepository : IReadWriteQueryRepository<int, ILanguage>
|
||||
/// </summary>
|
||||
/// <param name="isoCode">The ISO code of the language.</param>
|
||||
/// <returns>The language if found; otherwise, <c>null</c>.</returns>
|
||||
ILanguage? GetByIsoCode(string isoCode);
|
||||
Task<ILanguage?> GetByIsoCodeAsync(string isoCode);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a language identifier from its ISO code.
|
||||
@@ -20,7 +20,7 @@ public interface ILanguageRepository : IReadWriteQueryRepository<int, ILanguage>
|
||||
/// <remarks>
|
||||
/// <para>This can be optimized and bypass all deep cloning.</para>
|
||||
/// </remarks>
|
||||
int? GetIdByIsoCode(string? isoCode, bool throwOnNotFound = true);
|
||||
Task<int?> GetIdByIsoCodeAsync(string? isoCode, bool throwOnNotFound = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a language ISO code from its identifier.
|
||||
@@ -28,7 +28,7 @@ public interface ILanguageRepository : IReadWriteQueryRepository<int, ILanguage>
|
||||
/// <remarks>
|
||||
/// <para>This can be optimized and bypass all deep cloning.</para>
|
||||
/// </remarks>
|
||||
string? GetIsoCodeById(int? id, bool throwOnNotFound = true);
|
||||
Task<string?> GetIsoCodeByIdAsync(int? id, bool throwOnNotFound = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default language ISO code.
|
||||
@@ -36,7 +36,7 @@ public interface ILanguageRepository : IReadWriteQueryRepository<int, ILanguage>
|
||||
/// <remarks>
|
||||
/// <para>This can be optimized and bypass all deep cloning.</para>
|
||||
/// </remarks>
|
||||
string GetDefaultIsoCode();
|
||||
Task<string> GetDefaultIsoCodeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default language identifier.
|
||||
@@ -44,7 +44,7 @@ public interface ILanguageRepository : IReadWriteQueryRepository<int, ILanguage>
|
||||
/// <remarks>
|
||||
/// <para>This can be optimized and bypass all deep cloning.</para>
|
||||
/// </remarks>
|
||||
int? GetDefaultId();
|
||||
Task<int?> GetDefaultIdAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets multiple language ISO codes from the provided Ids.
|
||||
@@ -52,5 +52,5 @@ public interface ILanguageRepository : IReadWriteQueryRepository<int, ILanguage>
|
||||
/// <param name="ids">The language Ids.</param>
|
||||
/// <param name="throwOnNotFound">Indicates whether to throw an exception if the provided Id is not found as a language.</param>
|
||||
/// <returns></returns>
|
||||
string[] GetIsoCodesByIds(ICollection<int> ids, bool throwOnNotFound = true);
|
||||
Task<string[]> GetIsoCodesByIdsAsync(ICollection<int> ids, bool throwOnNotFound = true);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Scoping.EFCore;
|
||||
|
||||
@@ -20,6 +21,8 @@ public abstract class AsyncRepositoryCachePolicyBase<TEntity, TId> : IAsyncRepos
|
||||
private readonly IRepositoryCacheVersionService _cacheVersionService;
|
||||
private readonly ICacheSyncService _cacheSyncService;
|
||||
|
||||
protected string EntityTypeCacheKey { get; } = RepositoryCacheKeys.GetKey<TEntity>();
|
||||
|
||||
protected AsyncRepositoryCachePolicyBase(
|
||||
IAppPolicyCache globalCache,
|
||||
IScopeAccessor scopeAccessor,
|
||||
@@ -97,4 +100,21 @@ public abstract class AsyncRepositoryCachePolicyBase<TEntity, TId> : IAsyncRepos
|
||||
/// Registers a change in the cache.
|
||||
/// </summary>
|
||||
protected async Task RegisterCacheChangeAsync() => await _cacheVersionService.SetCacheUpdatedAsync<TEntity>();
|
||||
|
||||
protected string GetEntityCacheKey(int id) => EntityTypeCacheKey + id;
|
||||
|
||||
protected string GetEntityCacheKey(TId? id)
|
||||
{
|
||||
if (EqualityComparer<TId>.Default.Equals(id, default))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (typeof(TId).IsValueType)
|
||||
{
|
||||
return EntityTypeCacheKey + id;
|
||||
}
|
||||
|
||||
return EntityTypeCacheKey + id?.ToString()?.ToUpperInvariant();
|
||||
}
|
||||
}
|
||||
|
||||
+33
-23
@@ -6,9 +6,11 @@ using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.EFCore;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.EFCore.Scoping;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Factories;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Querying;
|
||||
using Umbraco.Cms.Infrastructure.Scoping;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement.EFCore;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
||||
@@ -16,7 +18,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
||||
/// <summary>
|
||||
/// Represents a repository for doing CRUD operations for <see cref="Language" />
|
||||
/// </summary>
|
||||
internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>, ILanguageRepository
|
||||
internal sealed class LanguageRepository : AsyncEntityRepositoryBase<int, ILanguage>, ILanguageRepository
|
||||
{
|
||||
// We need to lock this dictionary every time we do an operation on it as the languageRepository is registered as a unique implementation
|
||||
// It is used to quickly get isoCodes by Id, or the reverse by avoiding (deep)cloning dtos
|
||||
@@ -25,7 +27,7 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
private readonly Dictionary<int, string> _idCodeMap = new();
|
||||
|
||||
public LanguageRepository(
|
||||
IScopeAccessor scopeAccessor,
|
||||
IEFCoreScopeAccessor<UmbracoDbContext> scopeAccessor,
|
||||
AppCaches cache,
|
||||
ILogger<LanguageRepository> logger,
|
||||
IRepositoryCacheVersionService repositoryCacheVersionService,
|
||||
@@ -42,22 +44,22 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
private FullDataSetRepositoryCachePolicy<ILanguage, int>? TypedCachePolicy =>
|
||||
CachePolicy as FullDataSetRepositoryCachePolicy<ILanguage, int>;
|
||||
|
||||
public ILanguage? GetByIsoCode(string isoCode)
|
||||
public async Task<ILanguage?> GetByIsoCodeAsync(string isoCode)
|
||||
{
|
||||
EnsureCacheIsPopulated();
|
||||
await EnsureCacheIsPopulatedAsync();
|
||||
|
||||
var id = GetIdByIsoCode(isoCode, false);
|
||||
return id.HasValue ? Get(id.Value) : null;
|
||||
var id = await GetIdByIsoCodeAsync(isoCode, false);
|
||||
return id.HasValue ? GetAsync(id.Value) : null;
|
||||
}
|
||||
|
||||
public int? GetIdByIsoCode(string? isoCode, bool throwOnNotFound = true)
|
||||
public async Task<int?> GetIdByIsoCodeAsync(string? isoCode, bool throwOnNotFound = true)
|
||||
{
|
||||
if (isoCode == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
EnsureCacheIsPopulated();
|
||||
await EnsureCacheIsPopulatedAsync();
|
||||
|
||||
lock (_codeIdMap)
|
||||
{
|
||||
@@ -75,14 +77,14 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
return null;
|
||||
}
|
||||
|
||||
public string? GetIsoCodeById(int? id, bool throwOnNotFound = true)
|
||||
public async Task<string?> GetIsoCodeByIdAsync(int? id, bool throwOnNotFound = true)
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
EnsureCacheIsPopulated();
|
||||
await EnsureCacheIsPopulatedAsync();
|
||||
|
||||
lock (_codeIdMap)
|
||||
{
|
||||
@@ -101,7 +103,7 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
}
|
||||
|
||||
// multi implementation of GetIsoCodeById
|
||||
public string[] GetIsoCodesByIds(ICollection<int> ids, bool throwOnNotFound = true)
|
||||
public async Task<string[]> GetIsoCodesByIdsAsync(ICollection<int> ids, bool throwOnNotFound = true)
|
||||
{
|
||||
var isoCodes = new string[ids.Count];
|
||||
|
||||
@@ -110,7 +112,7 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
return isoCodes;
|
||||
}
|
||||
|
||||
EnsureCacheIsPopulated();
|
||||
await EnsureCacheIsPopulatedAsync();
|
||||
|
||||
|
||||
lock (_codeIdMap)
|
||||
@@ -132,14 +134,22 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
return isoCodes;
|
||||
}
|
||||
|
||||
public string GetDefaultIsoCode() => GetDefault().IsoCode;
|
||||
public async Task<string> GetDefaultIsoCodeAsync()
|
||||
{
|
||||
ILanguage defaultLanguage = await GetDefaultAsync();
|
||||
return defaultLanguage.IsoCode;
|
||||
}
|
||||
|
||||
public int? GetDefaultId() => GetDefault().Id;
|
||||
public async Task<int?> GetDefaultIdAsync()
|
||||
{
|
||||
ILanguage defaultLanguage = await GetDefaultAsync();
|
||||
return defaultLanguage.Id;
|
||||
}
|
||||
|
||||
protected override IRepositoryCachePolicy<ILanguage, int> CreateCachePolicy() =>
|
||||
protected override IAsyncRepositoryCachePolicy<ILanguage, int> CreateCachePolicy() =>
|
||||
new FullDataSetRepositoryCachePolicy<ILanguage, int>(GlobalIsolatedCache, ScopeAccessor, RepositoryCacheVersionService, CacheSyncService, GetEntityId, /*expires:*/ false);
|
||||
|
||||
private ILanguage ConvertFromDto(LanguageDto dto)
|
||||
private async Task<ILanguage> ConvertFromDtoAsync(LanguageDto dto)
|
||||
{
|
||||
lock (_codeIdMap)
|
||||
{
|
||||
@@ -154,14 +164,14 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
}
|
||||
|
||||
// do NOT leak that language, it's not deep-cloned!
|
||||
private ILanguage GetDefault()
|
||||
private async Task<ILanguage> GetDefaultAsync()
|
||||
{
|
||||
// get all cached
|
||||
var languages =
|
||||
(TypedCachePolicy
|
||||
?.GetAllCached(
|
||||
PerformGetAll) // Try to get all cached non-cloned if using the correct cache policy (not the case in unit tests)
|
||||
?? CachePolicy.GetAll(Array.Empty<int>(), PerformGetAll)).ToList();
|
||||
?? await CachePolicy.GetAllAsync(Array.Empty<int>(), PerformGetAll)).ToList();
|
||||
|
||||
ILanguage? language = languages.FirstOrDefault(x => x.IsDefault);
|
||||
if (language != null)
|
||||
@@ -188,9 +198,9 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
|
||||
#region Overrides of RepositoryBase<int,Language>
|
||||
|
||||
protected override ILanguage? PerformGet(int id) => PerformGetAll([id]).FirstOrDefault();
|
||||
protected override async Task<ILanguage?> PerformGetAsync(int id) => PerformGetAll([id]).FirstOrDefault();
|
||||
|
||||
protected override IEnumerable<ILanguage> PerformGetAll(params int[]? ids)
|
||||
protected override async Task<IEnumerable<ILanguage>> PerformGetAll(params int[]? ids)
|
||||
{
|
||||
Sql<ISqlContext> sql = GetBaseQuery(false).Where<LanguageDto>(x => x.Id > 0);
|
||||
if (ids?.Any() ?? false)
|
||||
@@ -221,7 +231,7 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
}
|
||||
}
|
||||
|
||||
var languages = languageDtos.Select(ConvertFromDto).OrderBy(x => x.Id).ToList();
|
||||
var languages = languageDtos.Select(ConvertFromDtoAsync).OrderBy(x => x.Id).ToList();
|
||||
return languages;
|
||||
}
|
||||
|
||||
@@ -420,7 +430,7 @@ internal sealed class LanguageRepository : EntityRepositoryBase<int, ILanguage>,
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureCacheIsPopulated()
|
||||
private async Task EnsureCacheIsPopulatedAsync()
|
||||
{
|
||||
// ensure cache is populated, in a non-expensive way
|
||||
if (TypedCachePolicy != null)
|
||||
|
||||
Reference in New Issue
Block a user