Skip to content

Commit

Permalink
Merge pull request #51 from Axemasta/feature/memory-cache
Browse files Browse the repository at this point in the history
Add InMemory Cache Provider
  • Loading branch information
Axemasta authored Feb 25, 2025
2 parents 541964d + df9ed70 commit 61b7fb6
Show file tree
Hide file tree
Showing 14 changed files with 385 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/mocale-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: Build
run: dotnet build --no-restore --configuration Release
- name: Test
run: dotnet test --no-build --verbosity normal --collect:"XPlat Code Coverage"
run: dotnet test --no-build --configuration Release --verbosity normal --collect:"XPlat Code Coverage"
if: github.event_name == 'pull_request'
- name: Publish Code Coverage To PR
uses: 5monkeys/cobertura-action@v13
Expand Down
18 changes: 9 additions & 9 deletions directory.packages.props
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.Maui.Controls" Version="$(MauiVersion)"/>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageVersion Include="ResXResourceReader.NetStandard" Version="1.3.0" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.2" />
<PackageVersion Include="Azure.Core" Version="1.45.0" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.23.0" />
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
<PackageVersion Include="SQLitePCLRaw.bundle_green" Version="2.1.10" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0"/>
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
<PackageVersion Include="Humanizer.Core" Version="2.14.1" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="CommunityToolkit.Maui" Version="11.1.0" />
Expand All @@ -20,6 +21,5 @@
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="9.0.2" />
<PackageVersion Include="Ardalis.GuardClauses" Version="5.0.0" />
<PackageVersion Include="Nerdbank.GitVersioning" Version="3.7.115" />
</ItemGroup>
</Project>

</ItemGroup>
</Project>
8 changes: 4 additions & 4 deletions samples/Mocale.Samples/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ public static MauiApp CreateMauiApp()
AttributePropertyName = nameof(MocaleTranslationKeyAttribute.Key),
});
})
.UseSqliteCache(config =>
{
config.UpdateInterval = TimeSpan.FromDays(1);
})
//.UseSqliteCache(config =>
//{
// config.UpdateInterval = TimeSpan.FromDays(1);
//})
.UseEmbeddedResources(config =>
{
config.ResourcesPath = "Locales";
Expand Down
7 changes: 6 additions & 1 deletion src/Mocale.Cache.SQLite/MocaleBuilderExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ public static class MocaleBuilderExtension
/// <param name="configureSql"></param>
/// <returns></returns>
public static MocaleBuilder UseSqliteCache(this MocaleBuilder builder, Action<SqliteConfig> configureSql)
{
return UseSqliteCache(builder, FileSystem.Current, configureSql);
}

internal static MocaleBuilder UseSqliteCache(this MocaleBuilder builder, IFileSystem fileSystem, Action<SqliteConfig> configureSql)
{
var config = new SqliteConfig
{
DatabaseDirectory = FileSystem.AppDataDirectory,
DatabaseDirectory = fileSystem.AppDataDirectory,
};

configureSql(config);
Expand Down
8 changes: 6 additions & 2 deletions src/Mocale/AppBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Microsoft.Extensions.Caching.Memory;
using Mocale.Cache;
using Mocale.Exceptions;
using Mocale.Managers;
using Mocale.Providers;
Expand Down Expand Up @@ -68,8 +70,10 @@ public static MauiAppBuilder UseMocale(

if (!mocaleBuilder.CacheProviderRegistered)
{
// TODO: Initialize in memory provider
throw new InitializationException("No cache provider has been registered. In the future there will be an in memory provider, for now please install and register the SQLite cache provider");
mauiAppBuilder.Services.AddTransient<MemoryCache>();
mauiAppBuilder.Services.AddSingleton<InMemoryCacheManager>();
mauiAppBuilder.Services.AddSingleton<ILocalisationCacheManager>(x => x.GetRequiredService<InMemoryCacheManager>());
mauiAppBuilder.Services.AddSingleton<ICacheUpdateManager>(x => x.GetRequiredService<InMemoryCacheManager>());
}

return mauiAppBuilder;
Expand Down
44 changes: 44 additions & 0 deletions src/Mocale/Cache/InMemoryCacheManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Globalization;
using Microsoft.Extensions.Caching.Memory;

namespace Mocale.Cache;

internal class InMemoryCacheManager(MemoryCache memoryCache) : ILocalisationCacheManager, ICacheUpdateManager
{
public bool CanUpdateCache(CultureInfo cultureInfo)
{
return !memoryCache.TryGetValue(cultureInfo, out _);
}

public void ClearCache(CultureInfo cultureInfo)
{
memoryCache.Remove(cultureInfo);
}

public void ClearCache()
{
memoryCache.Clear();
}

public Dictionary<string, string>? GetCachedLocalizations(CultureInfo cultureInfo)
{
if (memoryCache.TryGetValue<Dictionary<string, string>>(cultureInfo, out var cachedLocalizations))
{
return cachedLocalizations;
}

return null;
}

public bool SaveCachedLocalizations(CultureInfo cultureInfo, Dictionary<string, string> localizations)
{
memoryCache.Set(cultureInfo, localizations);

return true;
}

public bool SetCacheUpdated(CultureInfo cultureInfo)
{
return true;
}
}
3 changes: 2 additions & 1 deletion src/Mocale/Mocale.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="ResXResourceReader.NetStandard" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" PrivateAssets="all" />
<PackageReference Include="ResXResourceReader.NetStandard" PrivateAssets="all" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion src/directory.build.props
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Ardalis.GuardClauses"/>
<PackageReference Include="Ardalis.GuardClauses" PrivateAssets="all"/>
<PackageReference Include="Nerdbank.GitVersioning">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
Expand Down
148 changes: 148 additions & 0 deletions tests/Mocale.UnitTests/Cache/InMemoryCacheManagerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
using System.Globalization;
using Microsoft.Extensions.Caching.Memory;
using Mocale.Cache;

namespace Mocale.UnitTests.Cache;

public class InMemoryCacheManagerTests : FixtureBase, IDisposable
{
#region Setup

private readonly MemoryCache memoryCache = new(new MemoryCacheOptions());

public override object CreateSystemUnderTest()
{
return new InMemoryCacheManager(memoryCache);
}

public void Dispose()
{
memoryCache?.Dispose();
GC.SuppressFinalize(this);
}

#endregion Setup

#region Tests

[Fact]
public void CanUpdateCache_WhenKeyNotInCache_ReturnsTrue()
{
// Arrange
var culture = new CultureInfo("en-US");

// Act
var result = GetSut<InMemoryCacheManager>().CanUpdateCache(culture);

// Assert
Assert.True(result);
}

[Fact]
public void CanUpdateCache_WhenKeyInCache_ReturnsFalse()
{
// Arrange
var culture = new CultureInfo("en-US");
memoryCache.Set(culture, new Dictionary<string, string>()
{
{ "KeyOne", "ValueOne" }
});

// Act
var result = GetSut<InMemoryCacheManager>().CanUpdateCache(culture);

// Assert
Assert.False(result);
}

[Fact]
public void ClearCache_RemovesCacheEntry()
{
// Arrange
var culture = new CultureInfo("en-US");
memoryCache.Set(culture, new Dictionary<string, string>());

// Act
GetSut<InMemoryCacheManager>().ClearCache(culture);

// Assert
Assert.False(memoryCache.TryGetValue(culture, out _));
}

[Fact]
public void ClearCache_CallsClearMethod()
{
// Arrange
memoryCache.Set(new CultureInfo("en-US"), new Dictionary<string, string>());
memoryCache.Set(new CultureInfo("en-GB"), new Dictionary<string, string>());
memoryCache.Set(new CultureInfo("fr-FR"), new Dictionary<string, string>());

Assert.Equal(3, memoryCache.Count);

// Act
GetSut<InMemoryCacheManager>().ClearCache();

// Assert
Assert.Equal(0, memoryCache.Count);
}

[Fact]
public void GetCachedLocalizations_WhenInCache_ReturnsDictionary()
{
// Arrange
var culture = new CultureInfo("en-US");
var localizations = new Dictionary<string, string> { { "Hello", "Hola" } };
memoryCache.Set(culture, localizations);

// Act
var result = GetSut<InMemoryCacheManager>().GetCachedLocalizations(culture);

// Assert
Assert.NotNull(result);
Assert.Equal("Hola", result["Hello"]);
}

[Fact]
public void GetCachedLocalizations_WhenNotInCache_ReturnsNull()
{
// Arrange
var culture = new CultureInfo("en-US");

// Act
var result = GetSut<InMemoryCacheManager>().GetCachedLocalizations(culture);

// Assert
Assert.Null(result);
}

[Fact]
public void SaveCachedLocalizations_AddsEntryToCache()
{
// Arrange
var culture = new CultureInfo("en-US");
var localizations = new Dictionary<string, string> { { "Hello", "Hola" } };

// Act
var result = GetSut<InMemoryCacheManager>().SaveCachedLocalizations(culture, localizations);

// Assert
Assert.True(result);
Assert.True(memoryCache.TryGetValue(culture, out var cachedData));
Assert.Equal(localizations, cachedData);
}

[Fact]
public void SetCacheUpdated_AlwaysReturnsTrue()
{
// Arrange
var culture = new CultureInfo("en-US");

// Act
var result = GetSut<InMemoryCacheManager>().SetCacheUpdated(culture);

// Assert
Assert.True(result);
}

#endregion Tests
}
Loading

0 comments on commit 61b7fb6

Please sign in to comment.