Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Change Manager to Generic methods #2

Merged
merged 1 commit into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 13 additions & 14 deletions CacheBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
using CacheManager.CacheSource;
using CacheManager.CacheSource;
using CacheManager.Config;

namespace CacheManager;

/// <summary>
/// Simple cache builder
/// </summary>
/// <typeparam name="T">EasyCacheManager</typeparam>
public class CacheBuilder<T>
public class CacheBuilder
{
private readonly List<ICacheSourceWithGet<T>> _cacheSources = [];
private readonly List<ICacheSourceWithGet> _cacheSources = [];

/// <summary>
/// Add Memory Cache
/// </summary>
/// <param name="memoryConfig">Config</param>
/// <returns>CacheBuilder</returns>
public CacheBuilder<T> AddMemory(MemoryConfig memoryConfig)
public CacheBuilder AddMemory(MemoryConfig memoryConfig)
{
_cacheSources.Add(new MemoryCacheSource<T>(memoryConfig, 1));
_cacheSources.Add(new MemoryCacheSource(memoryConfig, 1));
return this;
}

Expand All @@ -27,9 +26,9 @@ public CacheBuilder<T> AddMemory(MemoryConfig memoryConfig)
/// </summary>
/// <param name="redisConfig">Config</param>
/// <returns>CacheBuilder</returns>
public CacheBuilder<T> AddRedis(RedisConfig redisConfig)
public CacheBuilder AddRedis(RedisConfig redisConfig)
{
_cacheSources.Add(new RedisCacheSource<T>(redisConfig, 2));
_cacheSources.Add(new RedisCacheSource(redisConfig, 2));
return this;
}

Expand All @@ -38,9 +37,9 @@ public CacheBuilder<T> AddRedis(RedisConfig redisConfig)
/// </summary>
/// <param name="dbConfig">Config</param>
/// <returns>CacheBuilder</returns>
public CacheBuilder<T> AddDb(DbConfig dbConfig)
public CacheBuilder AddDb(DbConfig dbConfig)
{
_cacheSources.Add(new DbCacheSourceWithGet<T>(dbConfig, 3));
_cacheSources.Add(new DbCacheSourceWithGet(dbConfig, 3));
return this;
}

Expand All @@ -49,9 +48,9 @@ public CacheBuilder<T> AddDb(DbConfig dbConfig)
/// </summary>
/// <param name="apiConfig">Config</param>
/// <returns>CacheBuilder</returns>
public CacheBuilder<T> AddApi(ApiConfig apiConfig)
public CacheBuilder AddApi(ApiConfig apiConfig)
{
_cacheSources.Add(new ApiCacheSourceWithGet<T>(apiConfig, 4));
_cacheSources.Add(new ApiCacheSourceWithGet(apiConfig, 4));
return this;
}

Expand All @@ -60,7 +59,7 @@ public CacheBuilder<T> AddApi(ApiConfig apiConfig)
/// </summary>
/// <param name="sourceWithGet">Your custom source</param>
/// <returns>CacheBuilder</returns>
public CacheBuilder<T> AddCustom(ICacheSourceWithGet<T> sourceWithGet)
public CacheBuilder AddCustom(ICacheSourceWithGet sourceWithGet)
{
_cacheSources.Add(sourceWithGet);
return this;
Expand All @@ -71,5 +70,5 @@ public CacheBuilder<T> AddCustom(ICacheSourceWithGet<T> sourceWithGet)
/// </summary>
/// <param name="lockConfig">Config</param>
/// <returns>EasyCacheManager</returns>
public EasyCacheManager<T> Build(LockConfig lockConfig) => new(_cacheSources, lockConfig);
public EasyCacheManager Build(LockConfig lockConfig) => new(_cacheSources, lockConfig);
}
9 changes: 9 additions & 0 deletions CacheManager.csproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<ItemGroup>
<EmbeddedResource Update="Resources.resx">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
</Project>
10 changes: 5 additions & 5 deletions CacheManagerIntegrationTest/EasyCacheManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class EasyCacheManagerTests : IAsyncLifetime
private RedisContainer _redisContainer = null!;
private IConnectionMultiplexer _redisConnection = null!;
private SqlConnection _sqlConnection = null!;
private EasyCacheManager<string> _easyCacheManager = null!;
private EasyCacheManager _easyCacheManager = null!;

public async Task InitializeAsync()
{
Expand Down Expand Up @@ -81,7 +81,7 @@ public async Task InitializeAsync()
await _sqlConnection.ExecuteAsync(StaticData.QueryToCreateTable).ConfigureAwait(false);

// Initialize Cache Manager with all sources
_easyCacheManager = new CacheBuilder<string>()
_easyCacheManager = new CacheBuilder()
.AddApi(new ApiConfig { Url = StaticData.Api })
.AddRedis(new RedisConfig { ConnectionString = redisConnectionString })
.AddDb(new DbConfig { ConnectionString = sqlConnectionString, Query = StaticData.QueryToSelect })
Expand Down Expand Up @@ -117,7 +117,7 @@ public async Task GetAsync_ShouldReturnData_FromDbAndSaveToMemoryAndRedis()
_ = await _sqlConnection.ExecuteAsync(StaticData.QueryToInsert).ConfigureAwait(true);

// Act
var result = await _easyCacheManager.GetAsync(StaticData.Key).ConfigureAwait(true);
var result = await _easyCacheManager.GetAsync<string>(StaticData.Key).ConfigureAwait(true);

// Assert
Assert.NotNull(result);
Expand All @@ -138,7 +138,7 @@ public async Task GetAsync_ShouldReturnData_FromApiAndSaveToMemoryAndRedis()
.RespondWithJson(StaticData.Value);

// Act
var result = await _easyCacheManager.GetAsync(StaticData.Key).ConfigureAwait(true);
var result = await _easyCacheManager.GetAsync<string>(StaticData.Key).ConfigureAwait(true);

// Assert
Assert.NotNull(result);
Expand All @@ -153,7 +153,7 @@ public async Task SetAsync_ShouldStoreData_InAllCacheSources()
// Act
await _easyCacheManager.SetAsync(StaticData.Key, StaticData.Value).ConfigureAwait(true);

var resultFromMemory = await _easyCacheManager.GetAsync(StaticData.Key).ConfigureAwait(true);
var resultFromMemory = await _easyCacheManager.GetAsync<string>(StaticData.Key).ConfigureAwait(true);

// Assert
Assert.Equal(StaticData.Value, resultFromMemory);
Expand Down
12 changes: 6 additions & 6 deletions CacheManagerLoadTest/EasyCacheManagerLoadTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class EasyCacheManagerLoadTest : IAsyncLifetime
private RedisContainer _redisContainer = null!;
private IConnectionMultiplexer _redisConnection = null!;
private SqlConnection _sqlConnection = null!;
private EasyCacheManager<string> _easyCacheManager = null!;
private EasyCacheManager _easyCacheManager = null!;

public async Task InitializeAsync()
{
Expand Down Expand Up @@ -82,7 +82,7 @@ public async Task InitializeAsync()
_ = await _sqlConnection.ExecuteAsync(StaticData.QueryToCreateTable).ConfigureAwait(false);

// Initialize Cache Manager with all sources
_easyCacheManager = new CacheBuilder<string>()
_easyCacheManager = new CacheBuilder()
.AddApi(new ApiConfig { Url = StaticData.Api })
.AddRedis(new RedisConfig { ConnectionString = redisConnectionString })
.AddDb(new DbConfig { ConnectionString = sqlConnectionString, Query = StaticData.QueryToSelect })
Expand Down Expand Up @@ -124,7 +124,7 @@ public async Task LoadTest_GetAndSet_AllShouldBeValid()

await _easyCacheManager.SetAsync(randomKey, randomKey).ConfigureAwait(true);

var response = await _easyCacheManager.GetAsync(randomKey).ConfigureAwait(true);
var response = await _easyCacheManager.GetAsync<string>(randomKey).ConfigureAwait(true);

if (response != randomKey)
{
Expand Down Expand Up @@ -157,7 +157,7 @@ public async Task LoadTest_GetFromApi_AllShouldBeValid()
.WithVerb(HttpMethod.Get)
.RespondWithJson(randomKey);

var response = await _easyCacheManager.GetAsync(randomKey).ConfigureAwait(true);
var response = await _easyCacheManager.GetAsync<string>(randomKey).ConfigureAwait(true);

if (response != randomKey)
{
Expand Down Expand Up @@ -191,7 +191,7 @@ public async Task LoadTest_GetFromApiJust50Percent_AllShouldBeValid()
.WithVerb(HttpMethod.Get)
.RespondWithJson(randomKey);

var response = await _easyCacheManager.GetAsync(randomKey).ConfigureAwait(true);
var response = await _easyCacheManager.GetAsync<string>(randomKey).ConfigureAwait(true);

if (response != randomKey)
{
Expand All @@ -216,7 +216,7 @@ public async Task LoadTest_GetFromApiJust50Percent_AllShouldBeValid()
.WithVerb(HttpMethod.Get)
.RespondWithJson(null);

var response = await _easyCacheManager.GetAsync(randomKey).ConfigureAwait(true);
var response = await _easyCacheManager.GetAsync<string>(randomKey).ConfigureAwait(true);

if (response != randomKey)
{
Expand Down
72 changes: 36 additions & 36 deletions CacheManagerUnitTest/EasyCacheManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ public async Task SetAsync_ShouldClearAndSetCacheOnAllSources()
const string Key = StaticData.Key;
const string Value = StaticData.Key;

var cacheSourceWithSet1 = new Mock<ICacheSourceWithGetWithSet<string>>();
var cacheSourceWithSet1 = new Mock<ICacheSourceWithGetWithSet>();
_ = cacheSourceWithSet1.Setup(x => x.Priority).Returns(1);
var cacheSourceWithSet2 = new Mock<ICacheSourceWithGetWithSet<string>>();
var cacheSourceWithSet2 = new Mock<ICacheSourceWithGetWithSet>();
_ = cacheSourceWithSet2.Setup(x => x.Priority).Returns(2);

var cacheSourceWithClear1 = new Mock<ICacheSourceWithGetWithClear<string>>();
var cacheSourceWithClear1 = new Mock<ICacheSourceWithGetWithClear>();
_ = cacheSourceWithClear1.Setup(x => x.Priority).Returns(3);
var cacheSourceWithClear2 = new Mock<ICacheSourceWithGetWithClear<string>>();
var cacheSourceWithClear2 = new Mock<ICacheSourceWithGetWithClear>();
_ = cacheSourceWithClear2.Setup(x => x.Priority).Returns(4);

var cacheSources = new List<ICacheSourceWithGet<string>> { cacheSourceWithSet1.Object, cacheSourceWithSet2.Object, cacheSourceWithClear1.Object, cacheSourceWithClear2.Object };
var cacheSources = new List<ICacheSourceWithGet> { cacheSourceWithSet1.Object, cacheSourceWithSet2.Object, cacheSourceWithClear1.Object, cacheSourceWithClear2.Object };

var cacheManager = new EasyCacheManager<string>(cacheSources, _lockConfig);
var cacheManager = new EasyCacheManager(cacheSources, _lockConfig);

// Act
await cacheManager.SetAsync(Key, Value).ConfigureAwait(true);
Expand All @@ -54,19 +54,19 @@ public async Task GetAsync_ShouldRetrieveFromCacheAndSetInHigherPrioritySources(
const string Key = StaticData.Key;
const string Value = StaticData.Key;

var cacheSource1 = new Mock<ICacheSourceWithGetWithSet<string>>();
var cacheSource1 = new Mock<ICacheSourceWithGetWithSet>();
_ = cacheSource1.Setup(x => x.Priority).Returns(2);
_ = cacheSource1.Setup(x => x.GetAsync(It.IsAny<string>())).ReturnsAsync(Value);
_ = cacheSource1.Setup(x => x.GetAsync<string>(It.IsAny<string>())).ReturnsAsync(Value);

var cacheSource2 = new Mock<ICacheSourceWithGetWithSet<string>>();
var cacheSource2 = new Mock<ICacheSourceWithGetWithSet>();
_ = cacheSource2.Setup(x => x.Priority).Returns(1);
_ = cacheSource2.Setup(x => x.GetAsync(It.IsAny<string>())).ReturnsAsync((string)null!);
_ = cacheSource2.Setup(x => x.GetAsync<string>(It.IsAny<string>())).ReturnsAsync((string)null!);

var cacheSources = new List<ICacheSourceWithGet<string>> { cacheSource1.Object, cacheSource2.Object };
var cacheManager = new EasyCacheManager<string>(cacheSources, _lockConfig);
var cacheSources = new List<ICacheSourceWithGet> { cacheSource1.Object, cacheSource2.Object };
var cacheManager = new EasyCacheManager(cacheSources, _lockConfig);

// Act
var result = await cacheManager.GetAsync(Key).ConfigureAwait(true);
var result = await cacheManager.GetAsync<string>(Key).ConfigureAwait(true);

// Assert
Assert.Equal(Value, result);
Expand All @@ -77,33 +77,33 @@ public async Task GetAsync_ShouldRetrieveFromCacheAndSetInHigherPrioritySources(
public void Constructor_ShouldThrowException_WhenCacheSourcesIsNull()
{
// Act & Assert
_ = Assert.Throws<ArgumentException>(() => new EasyCacheManager<string>(null!, _lockConfig));
_ = Assert.Throws<ArgumentException>(() => new EasyCacheManager(null!, _lockConfig));
}

[Fact]
public void Constructor_ShouldThrowException_WhenLockConfigIsNull()
{
// Arrange
var cacheSource = new Mock<ICacheSourceWithGet<string>>().Object;
var cacheSources = new List<ICacheSourceWithGet<string>> { cacheSource };
var cacheSource = new Mock<ICacheSourceWithGet>().Object;
var cacheSources = new List<ICacheSourceWithGet> { cacheSource };

// Act & Assert
_ = Assert.Throws<ArgumentException>(() => new EasyCacheManager<string>(cacheSources, null!));
_ = Assert.Throws<ArgumentException>(() => new EasyCacheManager(cacheSources, null!));
}

[Fact]
public void Constructor_ShouldThrowException_WhenDuplicatePrioritiesExist()
{
// Arrange
var cacheSource1 = new Mock<ICacheSourceWithGet<string>>();
var cacheSource1 = new Mock<ICacheSourceWithGet>();
_ = cacheSource1.Setup(x => x.Priority).Returns(1);
var cacheSource2 = new Mock<ICacheSourceWithGet<string>>();
var cacheSource2 = new Mock<ICacheSourceWithGet>();
_ = cacheSource2.Setup(x => x.Priority).Returns(1);

var cacheSources = new List<ICacheSourceWithGet<string>> { cacheSource1.Object, cacheSource2.Object };
var cacheSources = new List<ICacheSourceWithGet> { cacheSource1.Object, cacheSource2.Object };

// Act & Assert
var exception = Assert.Throws<ArgumentException>(() => new EasyCacheManager<string>(cacheSources, _lockConfig));
var exception = Assert.Throws<ArgumentException>(() => new EasyCacheManager(cacheSources, _lockConfig));
Assert.Contains("Duplicate priority values found", exception.Message, StringComparison.OrdinalIgnoreCase);
}

Expand All @@ -114,40 +114,40 @@ public async Task GetAsync_ShouldGetFromApiAndSetToOther_ValidData()
const string Key = StaticData.Key;
const string Value = StaticData.Key;

var memoryCacheSource = new Mock<ICacheSourceWithGetWithSetAndClear<string>>();
var redisCacheSource = new Mock<ICacheSourceWithGetWithSetAndClear<string>>();
var dbCacheSource = new Mock<ICacheSourceWithGet<string>>();
var apiCacheSource = new Mock<ICacheSourceWithGet<string>>();
var memoryCacheSource = new Mock<ICacheSourceWithGetWithSetAndClear>();
var redisCacheSource = new Mock<ICacheSourceWithGetWithSetAndClear>();
var dbCacheSource = new Mock<ICacheSourceWithGet>();
var apiCacheSource = new Mock<ICacheSourceWithGet>();

_ = memoryCacheSource.Setup(x => x.GetAsync(Key)).ReturnsAsync((string)null!);
_ = memoryCacheSource.Setup(x => x.GetAsync<string>(Key)).ReturnsAsync((string)null!);
_ = memoryCacheSource.Setup(x => x.SetAsync(Key, Value));
_ = memoryCacheSource.Setup(x => x.ClearAsync(Key));
_ = memoryCacheSource.Setup(x => x.Priority).Returns(1);

_ = redisCacheSource.Setup(x => x.GetAsync(Key)).ReturnsAsync((string)null!);
_ = redisCacheSource.Setup(x => x.GetAsync<string>(Key)).ReturnsAsync((string)null!);
_ = redisCacheSource.Setup(x => x.SetAsync(Key, Value));
_ = redisCacheSource.Setup(x => x.ClearAsync(Key));
_ = redisCacheSource.Setup(x => x.Priority).Returns(2);

_ = dbCacheSource.Setup(x => x.GetAsync(Key)).ReturnsAsync((string)null!);
_ = dbCacheSource.Setup(x => x.GetAsync<string>(Key)).ReturnsAsync((string)null!);
_ = dbCacheSource.Setup(x => x.Priority).Returns(3);

_ = apiCacheSource.Setup(x => x.GetAsync(Key)).ReturnsAsync(Value);
_ = apiCacheSource.Setup(x => x.GetAsync<string>(Key)).ReturnsAsync(Value);
_ = apiCacheSource.Setup(x => x.Priority).Returns(4);

var cacheSources = new List<ICacheSourceWithGet<string>> { apiCacheSource.Object, dbCacheSource.Object, memoryCacheSource.Object, redisCacheSource.Object };
var cacheSources = new List<ICacheSourceWithGet> { apiCacheSource.Object, dbCacheSource.Object, memoryCacheSource.Object, redisCacheSource.Object };

// Act
var easyCacheManager = new EasyCacheManager<string>(cacheSources, _lockConfig);
var result = await easyCacheManager.GetAsync(Key).ConfigureAwait(true);
var easyCacheManager = new EasyCacheManager(cacheSources, _lockConfig);
var result = await easyCacheManager.GetAsync<string>(Key).ConfigureAwait(true);

//Assert
Assert.Equal(Value, result);

memoryCacheSource.Verify(x => x.GetAsync(Key), Times.Once, "Memory GetAsync should call only one");
redisCacheSource.Verify(x => x.GetAsync(Key), Times.Once, "Redis GetAsync should call only one");
dbCacheSource.Verify(x => x.GetAsync(Key), Times.Once, "Db GetAsync should call only one");
apiCacheSource.Verify(x => x.GetAsync(Key), Times.Once, "API GetAsync should call only one");
memoryCacheSource.Verify(x => x.GetAsync<string>(Key), Times.Once, "Memory GetAsync should call only one");
redisCacheSource.Verify(x => x.GetAsync<string>(Key), Times.Once, "Redis GetAsync should call only one");
dbCacheSource.Verify(x => x.GetAsync<string>(Key), Times.Once, "Db GetAsync should call only one");
apiCacheSource.Verify(x => x.GetAsync<string>(Key), Times.Once, "API GetAsync should call only one");

memoryCacheSource.Verify(x => x.SetAsync(Key, Value), Times.Once, "Memory SetAsync should call only one");
redisCacheSource.Verify(x => x.SetAsync(Key, Value), Times.Once, "Redis SetAsync should call only one");
Expand Down
9 changes: 4 additions & 5 deletions CacheSource/ApiCacheSourceWithGet.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using CacheManager.Config;
using CacheManager.Config;
using Flurl.Http;

namespace CacheManager.CacheSource;

/// <summary>
/// Get from Api
/// </summary>
/// <typeparam name="T">Result</typeparam>
public class ApiCacheSourceWithGet<T> : ICacheSourceWithGet<T>
public class ApiCacheSourceWithGet : ICacheSourceWithGet
{
private readonly ApiConfig _config;

Expand All @@ -28,7 +27,7 @@ public ApiCacheSourceWithGet(ApiConfig config, int priority)
/// </summary>
/// <param name="key">Key</param>
/// <returns>Result</returns>
public async Task<T?> GetAsync(string key)
public async Task<T?> GetAsync<T>(string key)
{
var result = _config.Type switch
{
Expand All @@ -53,7 +52,7 @@ public ApiCacheSourceWithGet(ApiConfig config, int priority)
/// Priority, Lowest priority - checked last
/// </summary>
#if NETSTANDARD2_0 || NET462
public int Priority { get; set; }
public int Priority { get; set; }
#else
public int Priority { get; init; }
#endif
Expand Down
Loading
Loading