Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public DistributedCacheAdapter(
var stored = DeserializeStored<T>(bytes);
if (stored is null)
{
RemoveInvalidEntry(key);
return null;
}

Expand All @@ -104,6 +105,7 @@ public DistributedCacheAdapter(
var stored = DeserializeStored<T>(bytes);
if (stored is null)
{
await RemoveInvalidEntryAsync(key, cancellationToken).ConfigureAwait(false);
return null;
}

Expand Down Expand Up @@ -308,6 +310,30 @@ private DistributedStoredEntry<T> CreateEnvelope<T>(T value, CacheEntryOptions o
}
}

private void RemoveInvalidEntry(CacheKey key)
{
try
{
_distributedCache.Remove(key.FullKey);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to remove invalid distributed cache entry for {Key}", key.FullKey);
}
}

private async Task RemoveInvalidEntryAsync(CacheKey key, CancellationToken cancellationToken)
{
try
{
await _distributedCache.RemoveAsync(key.FullKey, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to remove invalid distributed cache entry for {Key}", key.FullKey);
}
}

private static TimeSpan? ApplyJitter(TimeSpan? baseValue, TimeSpan? jitter)
{
if (!baseValue.HasValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ namespace CleanArchitecture.Extensions.Caching.Tests;

public class DistributedCacheAdapterTests
{
private static DistributedCacheAdapter CreateAdapter(CachingOptions? options = null, ICacheSerializer? serializer = null)
private static DistributedCacheAdapter CreateAdapter(CachingOptions? options = null, ICacheSerializer? serializer = null, IDistributedCache? distributed = null)
{
serializer ??= new SystemTextJsonCacheSerializer();
var distributed = new MemoryDistributedCache(MOptions.Create(new MemoryDistributedCacheOptions()));
distributed ??= new MemoryDistributedCache(MOptions.Create(new MemoryDistributedCacheOptions()));
var cachingOptions = options ?? CachingOptions.Default;
return new DistributedCacheAdapter(
distributed,
Expand Down Expand Up @@ -86,6 +86,34 @@ public void Skips_storing_when_payload_exceeds_limit()
Assert.Null(adapter.Get<string>(key));
}

[Fact]
public void Get_removes_corrupt_payload()
{
var distributed = new MemoryDistributedCache(MOptions.Create(new MemoryDistributedCacheOptions()));
var adapter = CreateAdapter(distributed: distributed);
var key = new CacheKey("ns", "Resource", "corrupt-sync");
distributed.Set(key.FullKey, "not-json"u8.ToArray(), new DistributedCacheEntryOptions());

var cached = adapter.Get<string>(key);

Assert.Null(cached);
Assert.Null(distributed.Get(key.FullKey));
}

[Fact]
public async Task GetAsync_removes_corrupt_payload()
{
var distributed = new MemoryDistributedCache(MOptions.Create(new MemoryDistributedCacheOptions()));
var adapter = CreateAdapter(distributed: distributed);
var key = new CacheKey("ns", "Resource", "corrupt-async");
await distributed.SetAsync(key.FullKey, "not-json"u8.ToArray(), new DistributedCacheEntryOptions());

var cached = await adapter.GetAsync<string>(key);

Assert.Null(cached);
Assert.Null(await distributed.GetAsync(key.FullKey));
}

[Fact]
public async Task Uses_serializer_content_type()
{
Expand Down
Loading