Skip to content

Commit a5fef5d

Browse files
committed
Add reset behavior
1 parent 5796ad9 commit a5fef5d

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed

LinkDotNet.Blog.Infrastructure/Persistence/CachedRepository.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
using System;
22
using System.Linq.Expressions;
3+
using System.Threading;
34
using System.Threading.Tasks;
45
using LinkDotNet.Blog.Domain;
56
using Microsoft.Extensions.Caching.Memory;
7+
using Microsoft.Extensions.Primitives;
68
using X.PagedList;
79

810
namespace LinkDotNet.Blog.Infrastructure.Persistence
911
{
1012
public class CachedRepository<T> : IRepository<T>
1113
where T : Entity
1214
{
15+
private static CancellationTokenSource resetToken = new();
16+
1317
private readonly IRepository<T> repository;
18+
1419
private readonly IMemoryCache memoryCache;
1520

1621
public CachedRepository(IRepository<T> repository, IMemoryCache memoryCache)
@@ -19,12 +24,18 @@ public CachedRepository(IRepository<T> repository, IMemoryCache memoryCache)
1924
this.memoryCache = memoryCache;
2025
}
2126

27+
private static MemoryCacheEntryOptions Options => new()
28+
{
29+
ExpirationTokens = { new CancellationChangeToken(resetToken.Token) },
30+
AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(7),
31+
};
32+
2233
public async Task<T> GetByIdAsync(string id)
2334
{
2435
if (!memoryCache.TryGetValue(id, out T value))
2536
{
2637
value = await repository.GetByIdAsync(id);
27-
memoryCache.Set(id, value);
38+
memoryCache.Set(id, value, Options);
2839
}
2940

3041
return value;
@@ -40,24 +51,34 @@ public async Task<IPagedList<T>> GetAllAsync(
4051
var key = $"{filter?.Body}-{orderBy?.Body}-{descending}-{page}-{pageSize}";
4152
return await memoryCache.GetOrCreate(key, async e =>
4253
{
43-
e.SetOptions(new MemoryCacheEntryOptions
44-
{
45-
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1),
46-
});
54+
e.SetOptions(Options);
4755
return await repository.GetAllAsync(filter, orderBy, descending, page, pageSize);
4856
});
4957
}
5058

5159
public async Task StoreAsync(T entity)
5260
{
53-
memoryCache.Set(entity.Id, entity, TimeSpan.FromHours(1));
61+
ResetCache();
62+
memoryCache.Set(entity.Id, entity, Options);
5463
await repository.StoreAsync(entity);
5564
}
5665

5766
public async Task DeleteAsync(string id)
5867
{
68+
ResetCache();
5969
memoryCache.Remove(id);
6070
await repository.DeleteAsync(id);
6171
}
72+
73+
private static void ResetCache()
74+
{
75+
if (resetToken is { IsCancellationRequested: false, Token: { CanBeCanceled: true } })
76+
{
77+
resetToken.Cancel();
78+
resetToken.Dispose();
79+
}
80+
81+
resetToken = new CancellationTokenSource();
82+
}
6283
}
6384
}

LinkDotNet.Blog.UnitTests/Infrastructure/Persistence/CachedRepositoryTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,25 @@ public async Task ShouldDelete()
121121
repositoryMock.Verify(r => r.DeleteAsync("id"), Times.Once);
122122
}
123123

124+
[Fact]
125+
public async Task ShouldGetFreshDataAfterDelete()
126+
{
127+
SetupRepository();
128+
await sut.GetAllAsync();
129+
await sut.DeleteAsync("some_id");
130+
131+
await sut.GetAllAsync();
132+
133+
repositoryMock.Verify(
134+
r => r.GetAllAsync(
135+
It.IsAny<Expression<Func<BlogPost,bool>>>(),
136+
It.IsAny<Expression<Func<BlogPost,object>>>(),
137+
It.IsAny<bool>(),
138+
It.IsAny<int>(),
139+
It.IsAny<int>()),
140+
Times.Exactly(2));
141+
}
142+
124143
private void SetupRepository()
125144
{
126145
var blogPost = new BlogPostBuilder().Build();

LinkDotNet.Blog.Web/RegistrationExtensions/StorageProviderExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public static void AddStorageProvider(this IServiceCollection services, IConfigu
3030
}
3131

3232
services.AddScoped<IRepository<BlogPost>, Repository<BlogPost>>();
33+
services.AddMemoryCache();
3334
services.Decorate(typeof(IRepository<>), typeof(CachedRepository<>));
3435
}
3536
}

0 commit comments

Comments
 (0)