Skip to content

Commit

Permalink
Added test to show off issue with DeleteByPrefix not respecting cache… (
Browse files Browse the repository at this point in the history
#314)

* Added test to show off issue with DeleteByPrefix not respecting cache scopes

* Fixed failing delete by prefix tests
  • Loading branch information
niemyjski authored Sep 27, 2024
1 parent 40f70a8 commit 37599b9
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 1 deletion.
72 changes: 72 additions & 0 deletions src/Foundatio.TestHarness/Caching/CacheClientTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,78 @@ public virtual async Task CanRemoveByPrefixAsync()
}
}

public virtual async Task CanRemoveByPrefixWithScopedCachesAsync()
{
var cache = GetCacheClient();
if (cache == null)
return;

using (cache)
{
await cache.RemoveAllAsync();
var scopedCache1 = new ScopedCacheClient(cache, "scoped1");

const string cacheKey = "key";
await cache.SetAsync(cacheKey, 1);
await scopedCache1.SetAsync(cacheKey, 1);
Assert.Equal(1, (await cache.GetAsync<int>(cacheKey)).Value);
Assert.Equal(1, (await scopedCache1.GetAsync<int>(cacheKey)).Value);

// Remove by prefix should only remove the unscoped cache.
Assert.Equal(1, await cache.RemoveByPrefixAsync(cacheKey));
Assert.False(await cache.ExistsAsync(cacheKey));
Assert.True(await scopedCache1.ExistsAsync(cacheKey));
Assert.Equal(1, (await scopedCache1.GetAsync<int>(cacheKey)).Value);

// Add the unscoped cache value back.
await cache.SetAsync(cacheKey, 1);

// Remove by null key.
Assert.Equal(1, await scopedCache1.RemoveByPrefixAsync(null));
Assert.True(await cache.ExistsAsync(cacheKey));
Assert.False(await scopedCache1.ExistsAsync(cacheKey));

// Add the scoped cache value back.
await scopedCache1.SetAsync(cacheKey, 1);

Assert.Equal(2, await cache.RemoveByPrefixAsync(null));
Assert.False(await cache.ExistsAsync(cacheKey));
Assert.False(await scopedCache1.ExistsAsync(cacheKey));

// Reset client values
await cache.SetAsync(cacheKey, 1);
await scopedCache1.SetAsync(cacheKey, 1);

// Remove by empty key.
Assert.Equal(1, await scopedCache1.RemoveByPrefixAsync(String.Empty));
Assert.True(await cache.ExistsAsync(cacheKey));
Assert.False(await scopedCache1.ExistsAsync(cacheKey));

// Add the scoped cache value back.
await scopedCache1.SetAsync(cacheKey, 1);

Assert.Equal(2, await cache.RemoveByPrefixAsync(String.Empty));
Assert.False(await cache.ExistsAsync(cacheKey));
Assert.False(await scopedCache1.ExistsAsync(cacheKey));

// Reset client values
await cache.SetAsync(cacheKey, 1);
await scopedCache1.SetAsync(cacheKey, 1);

// Remove by *.
Assert.Equal(1, await scopedCache1.RemoveByPrefixAsync("*"));
Assert.True(await cache.ExistsAsync(cacheKey));
Assert.False(await scopedCache1.ExistsAsync(cacheKey));

// Reset client values
await scopedCache1.SetAsync(cacheKey, 1);

Assert.Equal(2, await cache.RemoveByPrefixAsync("*"));
Assert.False(await cache.ExistsAsync(cacheKey));
Assert.False(await scopedCache1.ExistsAsync(cacheKey));
}
}

public virtual async Task CanRemoveByPrefixMultipleEntriesAsync(int count)
{
var cache = GetCacheClient();
Expand Down
6 changes: 6 additions & 0 deletions src/Foundatio.TestHarness/Caching/HybridCacheClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ public override Task CanRemoveByPrefixAsync()
return base.CanRemoveByPrefixAsync();
}

[Fact]
public override Task CanRemoveByPrefixWithScopedCachesAsync()
{
return base.CanRemoveByPrefixWithScopedCachesAsync();
}

[Theory]
[InlineData(50)]
[InlineData(500)]
Expand Down
3 changes: 2 additions & 1 deletion src/Foundatio/Caching/InMemoryCacheClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ public Task<int> RemoveAllAsync(IEnumerable<string> keys = null)
public Task<int> RemoveByPrefixAsync(string prefix)
{
var keysToRemove = new List<string>();
var regex = new Regex(String.Concat(prefix, "*").Replace("*", ".*").Replace("?", ".+"));
string normalizedPrefix = String.IsNullOrWhiteSpace(prefix) ? "*" : prefix.Trim();
var regex = new Regex(String.Concat("^", Regex.Escape(normalizedPrefix.Contains("*") ? normalizedPrefix : $"{normalizedPrefix}*"), "$").Replace("\\*", ".*?"));
try
{
foreach (string key in _memory.Keys.ToList())
Expand Down
6 changes: 6 additions & 0 deletions tests/Foundatio.Tests/Caching/InMemoryCacheClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ public override Task CanRemoveByPrefixAsync()
return base.CanRemoveByPrefixAsync();
}

[Fact]
public override Task CanRemoveByPrefixWithScopedCachesAsync()
{
return base.CanRemoveByPrefixWithScopedCachesAsync();
}

[Theory]
[InlineData(50)]
[InlineData(500)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ public override Task CanRemoveByPrefixAsync()
return base.CanRemoveByPrefixAsync();
}

[Fact]
public override Task CanRemoveByPrefixWithScopedCachesAsync()
{
return base.CanRemoveByPrefixWithScopedCachesAsync();
}

[Theory]
[InlineData(50)]
[InlineData(500)]
Expand Down

0 comments on commit 37599b9

Please sign in to comment.