Skip to content
This repository has been archived by the owner on Nov 3, 2024. It is now read-only.

Commit

Permalink
https://github.com/valdisiljuconoks/localization-provider-opti/issues…
Browse files Browse the repository at this point in the history
…/220
  • Loading branch information
Valdis Iljuconoks committed Jun 5, 2024
1 parent 1545a45 commit ffe55c7
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 49 deletions.
2 changes: 1 addition & 1 deletion lib/localization-provider
Submodule localization-provider updated 21 files
+3 −3 Tests/DbLocalizationProvider.Storage.PostgreSql.Tests/DbLocalizationProvider.Storage.PostgreSql.Tests.csproj
+3 −3 Tests/DbLocalizationProvider.Storage.SqlServer.Tests/DbLocalizationProvider.Storage.SqlServer.Tests.csproj
+3 −3 Tests/DbLocalizationProvider.Tests/DbLocalizationProvider.Tests.csproj
+0 −18 Tests/DbLocalizationProvider.Tests/UnitTestCache.cs
+9 −9 push-packages.ps1
+4 −4 src/DbLocalizationProvider.Abstractions/DbLocalizationProvider.Abstractions.csproj
+4 −4 src/DbLocalizationProvider.AdminUI.Models/DbLocalizationProvider.AdminUI.Models.csproj
+5 −5 src/DbLocalizationProvider.Csv/DbLocalizationProvider.Csv.csproj
+4 −4 src/DbLocalizationProvider.Storage.AzureTables/DbLocalizationProvider.Storage.AzureTables.csproj
+5 −5 src/DbLocalizationProvider.Storage.PostgreSQL/DbLocalizationProvider.Storage.PostgreSql.csproj
+5 −5 src/DbLocalizationProvider.Storage.SqlServer/DbLocalizationProvider.Storage.SqlServer.csproj
+5 −5 src/DbLocalizationProvider.Translator.Azure/DbLocalizationProvider.Translator.Azure.csproj
+4 −4 src/DbLocalizationProvider.Xliff/DbLocalizationProvider.Xliff.csproj
+27 −9 src/DbLocalizationProvider/Cache/BaseCacheManager.cs
+1 −13 src/DbLocalizationProvider/Cache/DictionaryBasedCache.cs
+31 −0 src/DbLocalizationProvider/Cache/ICache.cs
+7 −0 src/DbLocalizationProvider/Cache/ICacheManager.cs
+2 −14 src/DbLocalizationProvider/ConfigurationContext.cs
+4 −4 src/DbLocalizationProvider/DbLocalizationProvider.csproj
+1 −1 src/DbLocalizationProvider/Queries/GetTranslation.cs
+4 −8 src/DbLocalizationProvider/TypeFactory.cs
18 changes: 8 additions & 10 deletions src/DbLocalizationProvider.AspNetCore/Cache/ClearCacheHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@

namespace DbLocalizationProvider.AspNetCore.Cache;

public class ClearCacheHandler : ICommandHandler<ClearCache.Command>
/// <summary>
/// Clears the cache.
/// </summary>
/// <param name="cache">Cache implementation</param>
public class ClearCacheHandler(ICacheManager cache) : ICommandHandler<ClearCache.Command>
{
private readonly ICacheManager _cache;

public ClearCacheHandler(ICacheManager cache)
{
_cache = cache;
}

/// <inheritdoc />
public void Execute(ClearCache.Command command)
{
foreach (var itemToRemove in InMemoryCacheManager.Entries)
foreach (var itemToRemove in cache.Keys)
{
_cache.Remove(itemToRemove.Key);
cache.Remove(itemToRemove);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,43 @@
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information

using System.Collections.Concurrent;
using System.Collections.Generic;
using DbLocalizationProvider.Cache;
using Microsoft.Extensions.Caching.Memory;

namespace DbLocalizationProvider.AspNetCore.Cache;

public class InMemoryCacheManager : ICacheManager
/// <summary>
/// Cache using IMemoryCache as a storage.
/// </summary>
public class InMemoryCache : ICache
{
// this is used in cache helper to enumerate over known entries and remove what's needed
// implemented because there is no way to enumerate keys using built-in cache provider
internal static readonly ConcurrentDictionary<string, bool> Entries = new();
private readonly IMemoryCache _memCache;

public InMemoryCacheManager(IMemoryCache memCache)
/// <summary>
/// Creates new instance.
/// </summary>
/// <param name="memCache">Memory cache</param>
public InMemoryCache(IMemoryCache memCache)
{
_memCache = memCache;
}

/// <inheritdoc />
public void Insert(string key, object value, bool insertIntoKnownResourceKeys)
{
_memCache.Set(key, value);
Entries.TryRemove(key, out _);
Entries.TryAdd(key, true);
}

/// <inheritdoc />
public object Get(string key)
{
return _memCache.Get(key);
}

/// <inheritdoc />
public void Remove(string key)
{
_memCache.Remove(key);
Entries.TryRemove(key, out _);
}

public event CacheEventHandler OnInsert;
public event CacheEventHandler OnRemove;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,43 @@ namespace DbLocalizationProvider.AspNetCore.ClientsideProvider;

internal class CacheHelper
{
private static readonly string _separator = "_|_";
private const string Separator = "_|_";

public static string GenerateKey(string filename, string language, bool isDebugMode, bool camelCase)
{
return $"{filename}{_separator}{language}__{(isDebugMode ? "debug" : "release")}__{camelCase}";
return $"{filename}{Separator}{language}__{(isDebugMode ? "debug" : "release")}__{camelCase}";
}

public static string GetContainerName(string key)
public static string? GetContainerName(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}

return !key.Contains(_separator) ? null : key.Substring(0, key.IndexOf(_separator, StringComparison.Ordinal));
return !key.Contains(Separator) ? null : key.Substring(0, key.IndexOf(Separator, StringComparison.Ordinal));
}

public static void CacheManagerOnRemove(CacheEventArgs args, ICacheManager cache)
{
// TODO: implement IEnumerable on cache manager
using (var existingKeys = InMemoryCacheManager.Entries.GetEnumerator())
using var existingKeys = cache.Keys.GetEnumerator();
var entriesToRemove = new List<string>();

while (existingKeys.MoveNext())
{
var entriesToRemove = new List<string>();
while (existingKeys.MoveNext())
{
var key = CacheKeyHelper.GetResourceKeyFromCacheKey(existingKeys.Current.Key);
var containerName = GetContainerName(key);

if (containerName != null
&& args.ResourceKey.StartsWith(containerName, StringComparison.InvariantCultureIgnoreCase))
{
entriesToRemove.Add(existingKeys.Current.Key);
}
}
var key = CacheKeyHelper.GetResourceKeyFromCacheKey(existingKeys.Current);
var containerName = GetContainerName(key);

foreach (var entry in entriesToRemove)
if (containerName != null
&& args.ResourceKey.StartsWith(containerName, StringComparison.InvariantCultureIgnoreCase))
{
cache.Remove(entry);
entriesToRemove.Add(existingKeys.Current);
}
}

foreach (var entry in entriesToRemove)
{
cache.Remove(entry);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ private string GenerateResponse(HttpContext context)
languageName,
debugMode,
camelCase,
context.RequestServices.GetService<IQueryExecutor>(),
context.RequestServices.GetService<IOptions<ConfigurationContext>>(),
context.RequestServices.GetService<ScanState>());
context.RequestServices.GetRequiredService<IQueryExecutor>(),
context.RequestServices.GetRequiredService<IOptions<ConfigurationContext>>(),
context.RequestServices.GetRequiredService<ScanState>());

cache.Insert(cacheKey, responseObject, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static class IServiceCollectionExtensions
/// <returns></returns>
public static IDbLocalizationProviderBuilder AddDbLocalizationProvider(
this IServiceCollection services,
Action<ConfigurationContext> setup = null)
Action<ConfigurationContext>? setup = null)
{
var ctx = new ConfigurationContext(services);
var factory = ctx.TypeFactory;
Expand All @@ -50,14 +50,17 @@ public static IDbLocalizationProviderBuilder AddDbLocalizationProvider(

// set to default in-memory provider
// only if we have IMemoryCache service registered
if (services.FirstOrDefault(d => d.ServiceType == typeof(IMemoryCache)) != null)
var memCacheDescriptor = services.FirstOrDefault(d => d.ServiceType == typeof(IMemoryCache));
if (memCacheDescriptor is { ServiceType: not null })
{
services.AddSingleton<ICacheManager, InMemoryCacheManager>();
ctx._baseCacheManager.SetInnerManager(sp => new InMemoryCache((IMemoryCache)sp.GetRequiredService(memCacheDescriptor.ServiceType)));
}

// run custom configuration setup (if any)
setup?.Invoke(ctx);

services.AddSingleton(ctx.CacheManager);

services.AddSingleton<ScanState>();
services.AddSingleton<ResourceKeyBuilder>();
services.AddSingleton<OldResourceKeyBuilder>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ public static void UseDbLocalizationProvider(this IServiceProvider serviceFactor
}

var context = serviceFactory.GetRequiredService<IOptions<ConfigurationContext>>();

// resolve inner cache (if set)
if (context.Value._baseCacheManager._implementationFactory != null)
{
context.Value._baseCacheManager.SetInnerManager(context.Value._baseCacheManager._implementationFactory(serviceFactory));
}

var usageConfigurator = serviceFactory.GetService<IUsageConfigurator>();

if (usageConfigurator != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,12 @@ public IEnumerable<LocalizationResource> Execute(GetAllResources.Query query)

if (resourceFromDb != null)
{
_configurationContext.Value.CacheManager.Insert(cacheKey, resourceFromDb, true);
result.Add(resourceFromDb);
}

_configurationContext.Value.CacheManager.Insert(cacheKey,
resourceFromDb ?? LocalizationResource.CreateNonExisting(key),
true);
}
}

Expand Down

0 comments on commit ffe55c7

Please sign in to comment.