Skip to content

Commit

Permalink
Refresh resources cache when the file changed
Browse files Browse the repository at this point in the history
  • Loading branch information
hishamco committed Mar 25, 2024
1 parent c83db38 commit c3dc71c
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 21 deletions.
52 changes: 52 additions & 0 deletions src/My.Extensions.Localization.Json/Internal/JsonFileWatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.IO;

namespace My.Extensions.Localization.Json.Internal;

public class JsonFileWatcher : IDisposable
{
private const string JsonExtension = "*.json";

private bool _disposed;

private readonly FileSystemWatcher _filesWatcher;

public event FileSystemEventHandler Changed;

public JsonFileWatcher(string rootDirectory)
{
_filesWatcher = new(rootDirectory)
{
Filter = JsonExtension,
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
EnableRaisingEvents = true
};
_filesWatcher.Changed += (s, e) => Changed?.Invoke(s, e);
}

~JsonFileWatcher()
{
Dispose(false);
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true);
}

public virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}

if (disposing)
{
_filesWatcher.Dispose();
}

_disposed = true;
}
}
62 changes: 48 additions & 14 deletions src/My.Extensions.Localization.Json/Internal/JsonResourceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,33 @@

namespace My.Extensions.Localization.Json.Internal;

public class JsonResourceManager(string resourcesPath, string resourceName = null)
public class JsonResourceManager
{
private readonly JsonFileWatcher _jsonFileWatcher;
private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, string>> _resourcesCache = new();

public string ResourceName { get; } = resourceName;

public string ResourcesPath { get; } = resourcesPath;
public JsonResourceManager(string resourcesPath, string resourceName = null)
{
ResourcesPath = resourcesPath;
ResourceName = resourceName;

_jsonFileWatcher = new(resourcesPath);
_jsonFileWatcher.Changed += RefreshResourcesCache;
}

public string ResourceName { get; }

public string ResourcesPath { get; }

public string ResourcesFilePath { get; private set; }

public virtual ConcurrentDictionary<string, string> GetResourceSet(CultureInfo culture, bool tryParents)
{
TryLoadResourceSet(culture);

if (!_resourcesCache.ContainsKey(culture.Name))
var key = $"{ResourceName}.{culture.Name}";
if (!_resourcesCache.ContainsKey(key))
{
return null;
}
Expand All @@ -30,7 +42,7 @@ public virtual ConcurrentDictionary<string, string> GetResourceSet(CultureInfo c
var allResources = new ConcurrentDictionary<string, string>();
do
{
if (_resourcesCache.TryGetValue(culture.Name, out var resources))
if (_resourcesCache.TryGetValue(key, out var resources))
{
foreach (var entry in resources)
{
Expand All @@ -45,7 +57,7 @@ public virtual ConcurrentDictionary<string, string> GetResourceSet(CultureInfo c
}
else
{
_resourcesCache.TryGetValue(culture.Name, out var resources);
_resourcesCache.TryGetValue(key, out var resources);

return resources;
}
Expand All @@ -63,7 +75,8 @@ public virtual string GetString(string name)

do
{
if (_resourcesCache.TryGetValue(culture.Name, out var resources))
var key = $"{ResourceName}.{culture.Name}";
if (_resourcesCache.TryGetValue(key, out var resources))
{
if (resources.TryGetValue(name, out var value))
{
Expand All @@ -86,7 +99,8 @@ public virtual string GetString(string name, CultureInfo culture)
return null;
}

if (!_resourcesCache.TryGetValue(culture.Name, out var resources))
var key = $"{ResourceName}.{culture.Name}";
if (!_resourcesCache.TryGetValue(key, out var resources))
{
return null;
}
Expand All @@ -102,7 +116,7 @@ private void TryLoadResourceSet(CultureInfo culture)
{
var file = Path.Combine(ResourcesPath, $"{culture.Name}.json");

GetOrAddResourceCache(file);
TryAddResources(file);
}
else
{
Expand All @@ -129,7 +143,7 @@ private void TryLoadResourceSet(CultureInfo culture)

culture = CultureInfo.GetCultureInfo(cultureName);

GetOrAddResourceCache(file);
TryAddResources(file);
}
}

Expand All @@ -147,14 +161,34 @@ IEnumerable<string> GetResourceFiles(string culture)
: [];
}

ConcurrentDictionary<string, string> GetOrAddResourceCache(string resourceFile)
void TryAddResources(string resourceFile)
{
return _resourcesCache.GetOrAdd(culture.Name, _ =>
var key = $"{ResourceName}.{culture.Name}";
if (!_resourcesCache.ContainsKey(key))
{
var resources = JsonResourceLoader.Load(resourceFile);

return new ConcurrentDictionary<string, string>(resources.ToDictionary(r => r.Key, r => r.Value));
});
_resourcesCache.TryAdd(key, new ConcurrentDictionary<string, string>(resources));
}
}
}

private void RefreshResourcesCache(object sender, FileSystemEventArgs e)
{
var key = Path.GetFileNameWithoutExtension(e.FullPath);
if (_resourcesCache.TryGetValue(key, out var resources))
{
if (!resources.IsEmpty)
{
resources.Clear();

var freshResources = JsonResourceLoader.Load(e.FullPath);

foreach (var item in freshResources)
{
_resourcesCache[key].TryAdd(item.Key, item.Value);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BenchmarkDotNet.Attributes;
using My.Extensions.Localization.Json.Internal;
using System.Globalization;
using System.IO;

namespace My.Extensions.Localization.Json.Benchmarks;

Expand All @@ -12,19 +13,16 @@ public class JsonResourceManagerBenchmark

static JsonResourceManagerBenchmark()
{
_jsonResourceManager = new JsonResourceManager("Resources\\fr-FR.json");
var resources = "Resources";
_jsonResourceManager = new JsonResourceManager(resources, Path.Combine("fr-FR.json"));
_frenchCulture = CultureInfo.GetCultureInfo("fr-FR");
}

[Benchmark]
public void EvaluateGetResourceSetWithoutCultureFallback()
{
_jsonResourceManager.GetResourceSet(_frenchCulture, tryParents: false);
}
=> _jsonResourceManager.GetResourceSet(_frenchCulture, tryParents: false);

[Benchmark]
public void EvaluateGetResourceSetWithCultureFallback()
{
_jsonResourceManager.GetResourceSet(_frenchCulture, tryParents: true);
}
=> _jsonResourceManager.GetResourceSet(_frenchCulture, tryParents: true);
}

0 comments on commit c3dc71c

Please sign in to comment.