Skip to content

Commit dbd86c0

Browse files
authored
Feature/6.4.0
* closes #77 * closes #78 * code coverage * code smell
1 parent bc0d5c0 commit dbd86c0

10 files changed

Lines changed: 240 additions & 13 deletions

File tree

src/OLT.EF.Core.Services/OltContextService.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ protected OltContextService(
3030

3131
#region [ Queryable Methods ]
3232

33-
protected virtual IQueryable<TEntity> InitializeQueryable<TEntity>() where TEntity : class, IOltEntity
34-
{
35-
return InitializeQueryable<TEntity>(false);
36-
}
37-
3833
protected virtual IQueryable<TEntity> InitializeQueryable<TEntity>(bool includeDeleted) where TEntity : class, IOltEntity
3934
{
4035
return Context.InitializeQueryable<TEntity>(includeDeleted);

src/OLT.EF.Core.Services/OltEntityService.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,29 @@ protected OltEntityService(
1818
{
1919
}
2020

21+
/// <summary>
22+
/// Used for Adding new Entities
23+
/// </summary>
2124
protected virtual DbSet<TEntity> Repository => Context.Set<TEntity>();
2225

23-
#region [ Get Queryable ]
26+
#region [ Queryable Methods ]
2427

25-
protected virtual IQueryable<TEntity> GetQueryable() => Repository;
28+
29+
/// <summary>
30+
/// Initializes Queryable for Methods. Override this for things like Inlude.
31+
/// </summary>
32+
/// <param name="includeDeleted"></param>
33+
/// <returns></returns>
34+
protected virtual IQueryable<TEntity> InitializeQueryable(bool includeDeleted)
35+
{
36+
return InitializeQueryable<TEntity>(includeDeleted);
37+
}
38+
39+
/// <summary>
40+
/// Returns Queryable using <seealso cref="InitializeQueryable"/> for non-deleted records
41+
/// </summary>
42+
/// <returns></returns>
43+
protected virtual IQueryable<TEntity> GetQueryable() => InitializeQueryable(false);
2644

2745
#endregion
2846

src/OLT.Extensions.Caching.Memory/OltMemoryCache.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,20 @@ public override Task<bool> ExistsAsync(string key)
8383
}
8484
return Task.FromResult(false);
8585
}
86+
87+
public override void Flush()
88+
{
89+
if (_memoryCache is MemoryCache memoryCache)
90+
{
91+
var percentage = 1.0; //100%
92+
memoryCache.Compact(percentage);
93+
}
94+
}
95+
96+
public override Task FlushAsync()
97+
{
98+
Flush();
99+
return Task.CompletedTask;
100+
}
86101
}
87102
}

src/OLT.Extensions.Caching.Redis/OltRedisCache.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.Extensions.Options;
1+
using Microsoft.Extensions.Caching.Memory;
2+
using Microsoft.Extensions.Options;
23
using StackExchange.Redis;
34
using StackExchange.Redis.Extensions.Core.Abstractions;
45
using System;
@@ -97,5 +98,16 @@ public override async Task<bool> ExistsAsync(string key)
9798
var redisDatabase = _redisFactory.GetDefaultRedisDatabase();
9899
return await redisDatabase.ExistsAsync(cacheKey);
99100
}
101+
102+
public override void Flush()
103+
{
104+
FlushAsync().GetAwaiter().GetResult();
105+
}
106+
107+
public override async Task FlushAsync()
108+
{
109+
var redisDatabase = _redisFactory.GetDefaultRedisDatabase();
110+
await redisDatabase.FlushDbAsync();
111+
}
100112
}
101113
}

src/OLT.Extensions.Caching.Redis/OltRedisCacheServiceCollectionExtensions.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,8 @@ public static IServiceCollection AddOltCacheRedis(this IServiceCollection servic
6060
{
6161
throw new ArgumentNullException(nameof(cacheKeyPrefix));
6262
}
63-
63+
6464
redisConfiguration.Name = redisConfiguration.Name ?? redisConfiguration.ConfigurationOptions.ClientName;
65-
6665

6766
services.AddSingleton((provider) => provider
6867
.GetRequiredService<IRedisClientFactory>()

src/OLT.Extensions.Caching.Shared/IOltCacheService.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ public interface IOltCacheService : IOltInjectableSingleton
5353
/// <returns>True if the key is present in cache. Othwerwise False</returns>
5454
Task<bool> ExistsAsync(string key);
5555

56+
/// <summary>
57+
/// Flushes all cache entries
58+
/// </summary>
59+
void Flush();
60+
61+
/// <summary>
62+
/// Flushes all cache entries
63+
/// </summary>
64+
Task FlushAsync();
5665
}
5766

5867
}

src/OLT.Extensions.Caching.Shared/OltCacheService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,7 @@ protected virtual string ToCacheKey(string key)
2727
public abstract Task RemoveAsync(string key);
2828
public abstract bool Exists(string key);
2929
public abstract Task<bool> ExistsAsync(string key);
30+
public abstract void Flush();
31+
public abstract Task FlushAsync();
3032
}
3133
}

tests/OLT.EF.Core.Services.Tests/Assets/Services/ContextService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public UserEntity CreateUser()
7676
public PersonEntity Get(bool includeDeleted, params IOltSearcher<PersonEntity>[] searchers) => GetQueryable(includeDeleted, searchers).FirstOrDefault();
7777
public PersonEntity Get(IOltSearcher<PersonEntity> searcher) => GetQueryable(searcher).FirstOrDefault();
7878
public List<PersonEntity> Get(bool includeDeleted) => GetQueryable<PersonEntity>(includeDeleted).ToList();
79-
public List<PersonEntity> GetNonDeleted() => InitializeQueryable<PersonEntity>().ToList();
79+
public List<PersonEntity> GetNonDeleted() => InitializeQueryable<PersonEntity>(false).ToList();
8080
public async Task<PersonEntity> GetAsync(IOltSearcher<PersonEntity> searcher) => await GetQueryable(searcher).FirstOrDefaultAsync();
8181

8282
public List<PersonEntity> GetPeopleOrdered(bool includeDeleted) => GetQueryable<PersonEntity>(includeDeleted, p => p.OrderBy(t => t.NameLast).ThenBy(t => t.NameFirst)).ToList();

tests/OLT.Extensions.Caching.Tests/MemoryCacheGetTests.cs

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Microsoft.Extensions.DependencyInjection;
44
using OLT.Core;
55
using System;
6+
using System.Collections.Generic;
67
using System.Threading;
78
using System.Threading.Tasks;
89
using Xunit;
@@ -79,9 +80,94 @@ public void NonAsyncTest()
7980

8081
oltMemoryCache.Remove(cacheKey);
8182
memoryCache.Get<OltPersonName>(cacheKey).Should().BeNull();
82-
oltMemoryCache.Exists(cacheKey).Should().BeFalse();
83+
oltMemoryCache.Exists(cacheKey).Should().BeFalse();
84+
8385
}
8486

87+
[Fact]
88+
public void FlushTests()
89+
{
90+
91+
var cacheKeys = new Dictionary<string, OltPersonName>();
92+
var services = new ServiceCollection();
93+
94+
services.AddOltCacheMemory(TimeSpan.FromMinutes(2));
95+
var provider = services.BuildServiceProvider();
96+
97+
var memoryCache = provider.GetRequiredService<IMemoryCache>();
98+
var oltMemoryCache = provider.GetRequiredService<IOltCacheService>();
99+
100+
for(var idx = 0; idx < 10; idx++)
101+
{
102+
var model = TestHelper.CreateModel();
103+
var cacheKey = $"cache-person-{Guid.NewGuid()}";
104+
cacheKeys.Add(cacheKey, model);
105+
oltMemoryCache.Get(cacheKey, () => TestHelper.CloneModel(model)).Should().BeEquivalentTo(model);
106+
memoryCache.Get<OltPersonName>(cacheKey).Should().BeEquivalentTo(model);
107+
}
108+
109+
foreach(var item in cacheKeys)
110+
{
111+
var newModel = TestHelper.CreateModel();
112+
var cacheKey = item.Key;
113+
var expected = item.Value;
114+
oltMemoryCache.Get(cacheKey, () => TestHelper.CloneModel(newModel)).Should().BeEquivalentTo(expected);
115+
memoryCache.Get<OltPersonName>(cacheKey).Should().BeEquivalentTo(expected);
116+
}
117+
118+
oltMemoryCache.Flush();
119+
120+
foreach (var item in cacheKeys)
121+
{
122+
var newModel = TestHelper.CreateModel();
123+
var cacheKey = item.Key;
124+
var expected = item.Value;
125+
oltMemoryCache.Get(cacheKey, () => TestHelper.CloneModel(newModel)).Should().BeEquivalentTo(newModel);
126+
memoryCache.Get<OltPersonName>(cacheKey).Should().BeEquivalentTo(newModel);
127+
}
128+
}
85129

130+
[Fact]
131+
public async Task FlushAsyncTests()
132+
{
133+
134+
var cacheKeys = new Dictionary<string, OltPersonName>();
135+
var services = new ServiceCollection();
136+
137+
services.AddOltCacheMemory(TimeSpan.FromMinutes(2));
138+
var provider = services.BuildServiceProvider();
139+
140+
var memoryCache = provider.GetRequiredService<IMemoryCache>();
141+
var oltMemoryCache = provider.GetRequiredService<IOltCacheService>();
142+
143+
for (var idx = 0; idx < 10; idx++)
144+
{
145+
var model = TestHelper.CreateModel();
146+
var cacheKey = $"cache-person-{Guid.NewGuid()}";
147+
cacheKeys.Add(cacheKey, model);
148+
(await oltMemoryCache.GetAsync(cacheKey, async () => await TestHelper.FakeAsync(model))).Should().BeEquivalentTo(model);
149+
memoryCache.Get<OltPersonName>(cacheKey).Should().BeEquivalentTo(model);
150+
}
151+
152+
foreach (var item in cacheKeys)
153+
{
154+
var newModel = TestHelper.CreateModel();
155+
var cacheKey = item.Key;
156+
var expected = item.Value;
157+
(await oltMemoryCache.GetAsync(cacheKey, async () => await TestHelper.FakeAsync(newModel))).Should().BeEquivalentTo(expected);
158+
memoryCache.Get<OltPersonName>(cacheKey).Should().BeEquivalentTo(expected);
159+
}
160+
161+
await oltMemoryCache.FlushAsync();
162+
163+
foreach (var item in cacheKeys)
164+
{
165+
var newModel = TestHelper.CreateModel();
166+
var cacheKey = item.Key;
167+
var expected = item.Value;
168+
(await oltMemoryCache.GetAsync(cacheKey, async () => await TestHelper.FakeAsync(newModel))).Should().BeEquivalentTo(newModel);
169+
memoryCache.Get<OltPersonName>(cacheKey).Should().BeEquivalentTo(newModel);
170+
}
171+
}
86172
}
87173
}

tests/OLT.Extensions.Caching.Tests/RedisCacheGet.cs

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
using FluentAssertions;
1+
using Faker;
2+
using FluentAssertions;
3+
using Microsoft.Extensions.Caching.Memory;
24
using Microsoft.Extensions.DependencyInjection;
35
using Microsoft.Extensions.Options;
46
using OLT.Core;
57
using OLT.Extensions.Caching.Tests.Assets;
68
using StackExchange.Redis;
9+
using StackExchange.Redis.Extensions.Core.Abstractions;
710
using StackExchange.Redis.Extensions.Core.Configuration;
811
using System;
12+
using System.Collections.Generic;
913
using System.Threading.Tasks;
1014
using Xunit;
1115

@@ -104,5 +108,92 @@ public async Task AsyncConfigTests()
104108
cacheService.Remove(cacheKey);
105109

106110
}
111+
112+
113+
114+
[Fact]
115+
public void FlushTests()
116+
{
117+
118+
var cacheKeys = new Dictionary<string, OltPersonName>();
119+
var services = new ServiceCollection();
120+
var config = new RedisConfiguration
121+
{
122+
ConnectionString = $"{_config.RedisCacheConnectionString.Replace("unit-test", "unit-test-flush")},allowAdmin=true,defaultDatabase=4"
123+
};
124+
125+
var provider = TestHelper.BuildRedisProvider(config, TimeSpan.FromMinutes(2), "flush-tests");
126+
127+
var cacheService = provider.GetRequiredService<IOltCacheService>();
128+
129+
for (var idx = 0; idx < 10; idx++)
130+
{
131+
var model = TestHelper.CreateModel();
132+
var cacheKey = $"cache-person-{Guid.NewGuid()}";
133+
cacheKeys.Add(cacheKey, model);
134+
cacheService.Get(cacheKey, () => TestHelper.CloneModel(model)).Should().BeEquivalentTo(model);
135+
}
136+
137+
foreach (var item in cacheKeys)
138+
{
139+
var newModel = TestHelper.CreateModel();
140+
var cacheKey = item.Key;
141+
var expected = item.Value;
142+
cacheService.Get(cacheKey, () => TestHelper.CloneModel(newModel)).Should().BeEquivalentTo(expected);
143+
}
144+
145+
cacheService.Flush();
146+
147+
foreach (var item in cacheKeys)
148+
{
149+
var newModel = TestHelper.CreateModel();
150+
var cacheKey = item.Key;
151+
var expected = item.Value;
152+
cacheService.Get(cacheKey, () => TestHelper.CloneModel(newModel)).Should().BeEquivalentTo(newModel);
153+
}
154+
}
155+
156+
[Fact]
157+
public async Task FlushAsyncTests()
158+
{
159+
160+
var cacheKeys = new Dictionary<string, OltPersonName>();
161+
var services = new ServiceCollection();
162+
163+
var config = new RedisConfiguration
164+
{
165+
ConnectionString = $"{_config.RedisCacheConnectionString.Replace("unit-test", "unit-test-flush-async")},allowAdmin=true,defaultDatabase=3"
166+
};
167+
168+
var provider = TestHelper.BuildRedisProvider(config, TimeSpan.FromMinutes(2), "async-flush-tests");
169+
170+
var cacheService = provider.GetRequiredService<IOltCacheService>();
171+
172+
for (var idx = 0; idx < 10; idx++)
173+
{
174+
var model = TestHelper.CreateModel();
175+
var cacheKey = $"cache-person-{Guid.NewGuid()}";
176+
cacheKeys.Add(cacheKey, model);
177+
(await cacheService.GetAsync(cacheKey, async () => await TestHelper.FakeAsync(model))).Should().BeEquivalentTo(model);
178+
}
179+
180+
foreach (var item in cacheKeys)
181+
{
182+
var newModel = TestHelper.CreateModel();
183+
var cacheKey = item.Key;
184+
var expected = item.Value;
185+
(await cacheService.GetAsync(cacheKey, async () => await TestHelper.FakeAsync(newModel))).Should().BeEquivalentTo(expected);
186+
}
187+
188+
await cacheService.FlushAsync();
189+
190+
foreach (var item in cacheKeys)
191+
{
192+
var newModel = TestHelper.CreateModel();
193+
var cacheKey = item.Key;
194+
var expected = item.Value;
195+
(await cacheService.GetAsync(cacheKey, async () => await TestHelper.FakeAsync(newModel))).Should().BeEquivalentTo(newModel);
196+
}
197+
}
107198
}
108199
}

0 commit comments

Comments
 (0)