Skip to content

Commit

Permalink
Added Set and Get methods to ICacheService
Browse files Browse the repository at this point in the history
  • Loading branch information
kubagdynia committed Dec 6, 2023
1 parent c2d9230 commit e975936
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 20 deletions.
18 changes: 13 additions & 5 deletions CacheDrive.ExampleConsoleApp/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@ public class App(ICacheService cacheService)
{
public async Task Run()
{
string cacheKey = "testKey";
// SetAsync, GetAsync and TryGetValue
string cacheKey1 = "testKey";
await cacheService.SetAsync(cacheKey1, "test text...");
var cachedValue1 = await cacheService.GetAsync<string>(cacheKey1);
Console.WriteLine($"GetAsync - cached value: {cachedValue1}");

await cacheService.SetAsync(cacheKey, "test text...");
Console.WriteLine(cacheService.TryGetValue(cacheKey1, out string cachedValue2)
? $"TryGetValue OK - cached value: {cachedValue2}"
: $"TryGetValue NOK - cached value: {cachedValue2}");

Console.WriteLine(cacheService.TryGetValue(cacheKey, out string cachedValue)
? $"OK: cached value - {cachedValue}"
: $"NOK: cached value - {cachedValue}");
// Set, Get
string cacheKey2 = "testKey2";
cacheService.Set(cacheKey2, 1234567);
int cachedValue3 = cacheService.Get<int>(cacheKey2);
Console.WriteLine($"Get - cached value: {cachedValue3} ");
}
}
96 changes: 87 additions & 9 deletions CacheDrive.Tests/CachingSimpleTypesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace CacheDrive.Tests;
public class CachingSimpleTypesTests
{
[Test]
public async Task SimpleTypesShouldBeProperlyCachedAndRestoredFromTheMemory()
public async Task SimpleTypesShouldBeProperlyCachedAndRestoredFromTheMemoryAsync()
{
// Arrange
ServiceProvider serviceProvider = TestHelper.CreateServiceProvider(
Expand All @@ -22,19 +22,19 @@ public async Task SimpleTypesShouldBeProperlyCachedAndRestoredFromTheMemory()
ICacheService cacheService = serviceProvider.GetRequiredService<ICacheService>();

// Act
(string key, int value) intItem = ("int_test", 10);
(string key, int value) intItem = ("int_test_async", 10);
await cacheService.SetAsync(intItem.key, intItem.value);

(string key, char value) charItem = ("char_test", 'p');
(string key, char value) charItem = ("char_test_async", 'p');
await cacheService.SetAsync(charItem.key, charItem.value);

(string key, float value) floatItem = ("float_test", 4.8f);
(string key, float value) floatItem = ("float_test_async", 4.8f);
await cacheService.SetAsync(floatItem.key, floatItem.value);

(string key, double value) doubleItem = ("double_test", 6.8d);
(string key, double value) doubleItem = ("double_test_async", 6.8d);
await cacheService.SetAsync(doubleItem.key, doubleItem.value);

(string key, bool value) boolItem = ("bool_test", true);
(string key, bool value) boolItem = ("bool_test_async", true);
await cacheService.SetAsync(boolItem.key, boolItem.value);

int cachedIntItem = await cacheService.GetAsync<int>(intItem.key);
Expand All @@ -50,9 +50,87 @@ public async Task SimpleTypesShouldBeProperlyCachedAndRestoredFromTheMemory()
cachedDoubleItem.Should().Be(doubleItem.value);
cachedBoolItem.Should().Be(boolItem.value);
}

[Test]
public void SimpleTypesShouldBeProperlyCachedAndRestoredFromTheMemory()
{
// Arrange
ServiceProvider serviceProvider = TestHelper.CreateServiceProvider(
DateTime.Now,
cacheEnabled: true,
cacheExpirationType: CacheExpirationType.Hours,
cacheExpiration: 2,
cacheType: CacheType.Memory);

ICacheService cacheService = serviceProvider.GetRequiredService<ICacheService>();

// Act
(string key, int value) intItem = ("int_test", 10);
cacheService.Set(intItem.key, intItem.value);

(string key, char value) charItem = ("char_test", 'p');
cacheService.Set(charItem.key, charItem.value);

(string key, float value) floatItem = ("float_test", 4.8f);
cacheService.Set(floatItem.key, floatItem.value);

(string key, double value) doubleItem = ("double_test", 6.8d);
cacheService.Set(doubleItem.key, doubleItem.value);

(string key, bool value) boolItem = ("bool_test", true);
cacheService.Set(boolItem.key, boolItem.value);

int cachedIntItem = cacheService.Get<int>(intItem.key);
char cachedCharItem = cacheService.Get<char>(charItem.key);
float cachedFloatItem = cacheService.Get<float>(floatItem.key);
double cachedDoubleItem = cacheService.Get<double>(doubleItem.key);
bool cachedBoolItem = cacheService.Get<bool>(boolItem.key);

// Assert
cachedIntItem.Should().Be(intItem.value);
cachedCharItem.Should().Be(charItem.value);
cachedFloatItem.Should().Be(floatItem.value);
cachedDoubleItem.Should().Be(doubleItem.value);
cachedBoolItem.Should().Be(boolItem.value);
}

[Test]
public async Task SimpleTypesShouldBeProperlyDeletedFromTheMemoryCache()
public async Task SimpleTypesShouldBeProperlyDeletedFromTheMemoryCacheAsync()
{
// Arrange
ServiceProvider serviceProvider = TestHelper.CreateServiceProvider(
DateTime.Now,
cacheEnabled: true,
cacheExpirationType: CacheExpirationType.Hours,
cacheExpiration: 2,
cacheType: CacheType.Memory);

ICacheService cacheService = serviceProvider.GetRequiredService<ICacheService>();

// Act

// Add 50 items
for (int i = 0; i < 50; i++)
{
await cacheService.SetAsync($"test_{i}_async", i);
}

// Delete every second element
for (int i = 0; i < 50; i++)
{
if ((i + 1) % 2 == 0)
{
await cacheService.DeleteAsync<int>($"test_{i}_async");
}
}

// // Assert
int countCachedItems = cacheService.CountCachedItems();
countCachedItems.Should().Be(25);
}

[Test]
public void SimpleTypesShouldBeProperlyDeletedFromTheMemoryCache()
{
// Arrange
ServiceProvider serviceProvider = TestHelper.CreateServiceProvider(
Expand All @@ -69,15 +147,15 @@ public async Task SimpleTypesShouldBeProperlyDeletedFromTheMemoryCache()
// Add 50 items
for (int i = 0; i < 50; i++)
{
await cacheService.SetAsync($"test_{i}", i);
cacheService.Set($"test_{i}", i);
}

// Delete every second element
for (int i = 0; i < 50; i++)
{
if ((i + 1) % 2 == 0)
{
await cacheService.DeleteAsync<int>($"test_{i}");
cacheService.Delete<int>($"test_{i}");
}
}

Expand Down
18 changes: 18 additions & 0 deletions CacheDrive/Services/ICacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ public interface ICacheService
/// </param>
/// <returns>true if the key was found in the cache, otherwise, false.</returns>
bool TryGetValue<T>(string key, out T value);

/// <summary>
/// Get the value associated with the specified key from the cache.
/// </summary>
/// <param name="key">The key of the value to get.</param>
/// <returns>The value contains the object from the cache with the specified
/// key or the default value of T, if the operation failed.
/// </returns>
T Get<T>(string key);

/// <summary>
/// Get the value associated with the specified key from the cache.
Expand All @@ -46,6 +55,15 @@ public interface ICacheService
/// </returns>
Task<T> GetAsync<T>(string key);

/// <summary>
/// Adds a value to the cache if the key does not already exist, or updates if the key already exists.
/// </summary>
/// <param name="key">The key to be added or whose value should be updated.</param>
/// <param name="value">The value to add or update.</param>
/// <param name="expirySeconds">After how many seconds a given value will expire in the cache. Optional parameter.
/// By default, the value is taken from the configuration.</param>
void Set<T>(string key, T value, int expirySeconds = 0);

/// <summary>
/// Adds a value to the cache if the key does not already exist, or updates if the key already exists.
/// </summary>
Expand Down
53 changes: 47 additions & 6 deletions CacheDrive/Services/MemoryCacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@ public bool TryGetValue<T>(string key, out T value)
return true;
}

public T Get<T>(string key)
{
CacheableItem<T> cachedItem = GetCacheable<CacheableItem<T>>(key);

if (cachedItem is null)
{
return default;
}

return cachedItem.Value;
}

public async Task<T> GetAsync<T>(string key)
{
CacheableItem<T> cachedItem = await GetCacheableAsync<CacheableItem<T>>(key);
Expand Down Expand Up @@ -113,8 +125,36 @@ public async Task<T> GetAsync<T>(string key)

return cachedItem.Unwrap<T>();
}

private T GetCacheable<T>(string key) where T : ICacheable
{
string cacheKey = T.GetCacheKey(key);

CachedItem cachedItem = Get(cacheKey);

if (cachedItem is null)
return default;

if (cachedItem.Expired(_dateService))
{
Delete(cachedItem);
return default;
}

private void Set<T>(T item, int expirySeconds = 0) where T : ICacheable
return cachedItem.Unwrap<T>();
}

public void Set<T>(string key, T value, int expirySeconds = 0)
{
SetCacheableItem(CacheableItem<T>.Create(key, value), expirySeconds);
}

public Task SetAsync<T>(string key, T value, int expirySeconds = 0)
{
return SetAsync(CacheableItem<T>.Create(key, value), expirySeconds);
}

private void SetCacheableItem<T>(T item, int expirySeconds = 0) where T : ICacheable
{
TimeSpan length = GetExpirationLength(expirySeconds);

Expand All @@ -131,11 +171,6 @@ public async Task<T> GetAsync<T>(string key)
Set(cachedItem);
}

public Task SetAsync<T>(string key, T value, int expirySeconds = 0)
{
return SetAsync(CacheableItem<T>.Create(key, value), expirySeconds);
}

private Task SetAsync<T>(T item, int expirySeconds = 0) where T : ICacheable
{
CachedItem cached = Get(item);
Expand Down Expand Up @@ -176,8 +211,14 @@ public Task<bool> DeleteAsync<T>(string key)
private Task<bool> DeleteAsync(string key)
=> key is null ? Task.FromResult(false) : Task.FromResult(Storage.TryRemove(key, out _));

private bool Delete(string key)
=> key is not null && Storage.TryRemove(key, out _);

private Task<bool> DeleteAsync(CachedItem item)
=> DeleteAsync(item.Key);

private bool Delete(CachedItem item)
=> Delete(item.Key);

public int CountCachedItems()
=> Storage.Count;
Expand Down

0 comments on commit e975936

Please sign in to comment.