Skip to content

Commit

Permalink
Merge pull request #10 from catcherwong/dev
Browse files Browse the repository at this point in the history
In-Memory And Hybrid Caching Provider Implement RemoveByPrefix(Async)
  • Loading branch information
catcherwong authored Feb 5, 2018
2 parents 32c6251 + 3f12a3e commit c219819
Show file tree
Hide file tree
Showing 10 changed files with 236 additions and 12 deletions.
26 changes: 21 additions & 5 deletions src/EasyCaching.HybridCache/HybridCachingProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,15 +326,31 @@ public async Task RefreshAsync<T>(string cacheKey, T cacheValue, TimeSpan expira
await this.RemoveAsync(cacheKey);
await this.SetAsync(cacheKey, cacheValue, expiration);
}


/// <summary>
/// Removes cached item by cachekey's prefix.
/// </summary>
/// <returns>The by prefix async.</returns>
/// <param name="prefix">Prefix.</param>
public void RemoveByPrefix(string prefix)
{
throw new NotImplementedException();
ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));

_localCachingProvider.RemoveByPrefix(prefix);
_distributedCachingProvider.RemoveByPrefix(prefix);
}

public Task RemoveByPrefixAsync(string prefix)

/// <summary>
/// Removes cached item by cachekey's prefix async.
/// </summary>
/// <returns>The by prefix async.</returns>
/// <param name="prefix">Prefix.</param>
public async Task RemoveByPrefixAsync(string prefix)
{
throw new NotImplementedException();
ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));

await _localCachingProvider.RemoveByPrefixAsync(prefix);
await _distributedCachingProvider.RemoveByPrefixAsync(prefix);
}
}
}
1 change: 1 addition & 0 deletions src/EasyCaching.InMemory/EasyCaching.InMemory.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" />
<PackageReference Include="ConcurrentHashSet" Version="1.0.2" />
</ItemGroup>
</Project>
48 changes: 45 additions & 3 deletions src/EasyCaching.InMemory/InMemoryCachingProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using EasyCaching.Core.Internal;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Linq;
using System.Threading.Tasks;

/// <summary>
Expand All @@ -16,6 +17,11 @@ public class InMemoryCachingProvider : IEasyCachingProvider
/// </summary>
private readonly IMemoryCache _cache;

/// <summary>
/// The cache keys.
/// </summary>
private readonly ConcurrentCollections.ConcurrentHashSet<string> _cacheKeys;

/// <summary>
/// <see cref="T:EasyCaching.InMemory.InMemoryCachingProvider"/>
/// is not distributed cache.
Expand All @@ -30,6 +36,7 @@ public class InMemoryCachingProvider : IEasyCachingProvider
public InMemoryCachingProvider(IMemoryCache cache)
{
this._cache = cache;
this._cacheKeys = new ConcurrentCollections.ConcurrentHashSet<string>();
}

/// <summary>
Expand Down Expand Up @@ -140,6 +147,8 @@ public void Remove(string cacheKey)
ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));

_cache.Remove(cacheKey);

_cacheKeys.TryRemove(cacheKey);
}

/// <summary>
Expand All @@ -152,6 +161,8 @@ public async Task RemoveAsync(string cacheKey)
ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));

await Task.Run(() => _cache.Remove(cacheKey));

_cacheKeys.TryRemove(cacheKey);
}

/// <summary>
Expand All @@ -169,6 +180,8 @@ public void Set<T>(string cacheKey, T cacheValue, TimeSpan expiration) where T :
ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration));

_cache.Set(cacheKey, cacheValue, expiration);

_cacheKeys.Add(cacheKey);
}


Expand All @@ -187,6 +200,8 @@ public async Task SetAsync<T>(string cacheKey, T cacheValue, TimeSpan expiration
ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration));

await Task.Run(() => _cache.Set(cacheKey, cacheValue, expiration));

_cacheKeys.Add(cacheKey);
}

/// <summary>
Expand Down Expand Up @@ -248,14 +263,41 @@ public async Task RefreshAsync<T>(string cacheKey, T cacheValue, TimeSpan expira
await this.SetAsync(cacheKey, cacheValue, expiration);
}

/// <summary>
/// Removes cached item by cachekey's prefix.
/// </summary>
/// <param name="prefix">Prefix.</param>
public void RemoveByPrefix(string prefix)
{
throw new NotImplementedException();
ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));

var keys = _cacheKeys.Where(x => x.StartsWith(prefix.Trim(),StringComparison.OrdinalIgnoreCase));
if(keys.Count()>0)
{
foreach (var item in keys)
{
this.Remove(item);
}
}
}

public Task RemoveByPrefixAsync(string prefix)
/// <summary>
/// Removes cached item by cachekey's prefix async.
/// </summary>
/// <returns>The by prefix async.</returns>
/// <param name="prefix">Prefix.</param>
public async Task RemoveByPrefixAsync(string prefix)
{
throw new NotImplementedException();
ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));

var keys = _cacheKeys.Where(x => x.StartsWith(prefix.Trim(), StringComparison.OrdinalIgnoreCase));
if (keys.Count() > 0)
{
foreach (var item in keys)
{
await this.RemoveAsync(item);
}
}
}
}
}
4 changes: 4 additions & 0 deletions src/EasyCaching.Memcached/DefaultMemcachedCachingProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ public async Task RefreshAsync<T>(string cacheKey, T cacheValue, TimeSpan expira
/// <param name="prefix">Prefix of CacheKey.</param>
public void RemoveByPrefix(string prefix)
{
ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));

var oldPrefixKey = _memcachedClient.Get(prefix)?.ToString();

var newValue = DateTime.UtcNow.Ticks.ToString();
Expand All @@ -288,6 +290,8 @@ public void RemoveByPrefix(string prefix)
/// <returns></returns>
public async Task RemoveByPrefixAsync(string prefix)
{
ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));

var oldPrefixKey = _memcachedClient.Get(prefix)?.ToString();

var newValue = DateTime.UtcNow.Ticks.ToString();
Expand Down
23 changes: 20 additions & 3 deletions test/EasyCaching.UnitTests/CachingTests/BaseCachingProviderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,6 @@ public async Task Exists_Cached_Value_Async_Should_Return_False()
Assert.False(flag);
}


[Theory]
[InlineData("")]
[InlineData(" ")]
Expand Down Expand Up @@ -316,7 +315,25 @@ public async Task Refresh_Async_Should_Throw_ArgumentOutOfRangeException_When_Ex
string cacheVlaue = "123";
var expiration = new TimeSpan(0, 0, -1);
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(async () => await _provider.SetAsync(cacheKey, cacheVlaue, expiration));
}
}

[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
public void RemoveByPrefix_Should_Throw_ArgumentNullException_When_CacheKey_IsNullOrWhiteSpace(string prefix)
{
Assert.Throws<ArgumentNullException>(() => _provider.RemoveByPrefix(prefix));
}

[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
public async Task RemoveByPrefix_Async_Should_Throw_ArgumentNullException_When_Prefix_IsNullOrWhiteSpace(string preifx)
{
await Assert.ThrowsAsync<ArgumentNullException>(async () => await _provider.RemoveByPrefixAsync(preifx));
}

protected Func<string> Create_Fake_Retriever_Return_String()
{
Expand All @@ -337,7 +354,7 @@ protected Func<string> Create_Fake_Retriever_Return_NULL()
}

protected Func<Task<string>> Create_Fake_Retriever_Return_String_Async()
{
{
var func = A.Fake<Func<Task<string>>>();

A.CallTo(() => func.Invoke()).Returns(Task.FromResult("123"));
Expand Down
56 changes: 56 additions & 0 deletions test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 +192,61 @@ public async Task Refresh_Async_Should_Succeed()

Assert.Equal("NewValue", act.Value);
}

[Fact]
public void RemoveByPrefix_Should_Succeed()
{
SetCacheItem("demo:1", "1");
SetCacheItem("demo:2", "2");
SetCacheItem("demo:3", "3");
SetCacheItem("demo:4", "4");
SetCacheItem("xxx:1", "xxx");

_provider.RemoveByPrefix("demo");

var demo1 = _provider.Get<string>("demo:1");
var demo2 = _provider.Get<string>("demo:2");
var demo3 = _provider.Get<string>("demo:3");
var demo4 = _provider.Get<string>("demo:4");
var xxx1 = _provider.Get<string>("xxx:1");

Assert.False(demo1.HasValue);
Assert.False(demo2.HasValue);
Assert.False(demo3.HasValue);
Assert.False(demo4.HasValue);
Assert.True(xxx1.HasValue);
}

[Fact]
public async Task RemoveByPrefixAsync_Should_Succeed()
{
SetCacheItem("demo:1", "1");
SetCacheItem("demo:2", "2");
SetCacheItem("demo:3", "3");
SetCacheItem("demo:4", "4");
SetCacheItem("xxx:1", "xxx");

await _provider.RemoveByPrefixAsync("demo");

var demo1 = _provider.Get<string>("demo:1");
var demo2 = _provider.Get<string>("demo:2");
var demo3 = _provider.Get<string>("demo:3");
var demo4 = _provider.Get<string>("demo:4");
var xxx1 = _provider.Get<string>("xxx:1");

Assert.False(demo1.HasValue);
Assert.False(demo2.HasValue);
Assert.False(demo3.HasValue);
Assert.False(demo4.HasValue);
Assert.True(xxx1.HasValue);
}

private void SetCacheItem(string cacheKey, string cacheValue)
{
_provider.Set(cacheKey, cacheValue, _defaultTs);

var val = _provider.Get<string>(cacheKey);
Assert.Equal(cacheValue, val.Value);
}
}
}
14 changes: 13 additions & 1 deletion test/EasyCaching.UnitTests/CachingTests/MemcachedProviderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,11 @@ public void RemoveByPrefix_Should_Succeed()

_provider.Set(prefixKey, prefixValue, TimeSpan.FromSeconds(120));


SetCacheItem("1", "1", prefixKey);
SetCacheItem("2", "2", prefixKey);
SetCacheItem("3", "3", prefixKey);
SetCacheItem("4", "4", prefixKey);
SetCacheItem("4", "4", "xxx");

_provider.RemoveByPrefix(prefixKey);

Expand All @@ -196,6 +196,11 @@ public void RemoveByPrefix_Should_Succeed()
GetCacheItem("3", prefixKey);
GetCacheItem("4", prefixKey);

var pre = _provider.Get<string>("xxx");
var cacheKey = string.Concat(pre, "4");
var val = _provider.Get<string>(cacheKey);
Assert.True(val.HasValue);

var afterPrefixValue = _provider.Get<string>(prefixKey);
Assert.NotEqual(prefixValue, afterPrefixValue.Value);
}
Expand All @@ -212,6 +217,7 @@ public async Task RemoveByPrefix_Async_Should_Succeed()
SetCacheItem("2", "2", prefixKey);
SetCacheItem("3", "3", prefixKey);
SetCacheItem("4", "4", prefixKey);
SetCacheItem("4", "4", "xxx");

await _provider.RemoveByPrefixAsync(prefixKey);

Expand All @@ -220,6 +226,12 @@ public async Task RemoveByPrefix_Async_Should_Succeed()
GetCacheItem("3", prefixKey);
GetCacheItem("4", prefixKey);

var pre = _provider.Get<string>("xxx");
var cacheKey = string.Concat(pre, "4");
var val = _provider.Get<string>(cacheKey);
Assert.True(val.HasValue);


var afterPrefixValue = _provider.Get<string>(prefixKey);
Assert.NotEqual(prefixValue, afterPrefixValue.Value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,5 +195,61 @@ public async Task Refresh_Async_Should_Succeed()

Assert.Equal("NewValue", act.Value);
}

[Fact]
public void RemoveByPrefix_Should_Succeed()
{
SetCacheItem("demo:1", "1");
SetCacheItem("demo:2", "2");
SetCacheItem("demo:3", "3");
SetCacheItem("demo:4", "4");
SetCacheItem("xxx:1", "1");

_provider.RemoveByPrefix("demo");

var demo1 = _provider.Get<string>("demo:1");
var demo2 = _provider.Get<string>("demo:2");
var demo3 = _provider.Get<string>("demo:3");
var demo4 = _provider.Get<string>("demo:4");
var xxx1 = _provider.Get<string>("xxx:1");

Assert.False(demo1.HasValue);
Assert.False(demo2.HasValue);
Assert.False(demo3.HasValue);
Assert.False(demo4.HasValue);
Assert.True(xxx1.HasValue);
}

[Fact]
public async Task RemoveByPrefixAsync_Should_Succeed()
{
SetCacheItem("demo:1", "1");
SetCacheItem("demo:2", "2");
SetCacheItem("demo:3", "3");
SetCacheItem("demo:4", "4");
SetCacheItem("xxx:1", "1");

await _provider.RemoveByPrefixAsync("demo");

var demo1 = _provider.Get<string>("demo:1");
var demo2 = _provider.Get<string>("demo:2");
var demo3 = _provider.Get<string>("demo:3");
var demo4 = _provider.Get<string>("demo:4");
var xxx1 = _provider.Get<string>("xxx:1");

Assert.False(demo1.HasValue);
Assert.False(demo2.HasValue);
Assert.False(demo3.HasValue);
Assert.False(demo4.HasValue);
Assert.True(xxx1.HasValue);
}

private void SetCacheItem(string cacheKey, string cacheValue)
{
_provider.Set(cacheKey, cacheValue, _defaultTs);

var val = _provider.Get<string>(cacheKey);
Assert.Equal(cacheValue, val.Value);
}
}
}
Loading

0 comments on commit c219819

Please sign in to comment.