Skip to content

Commit b4c29fc

Browse files
committed
Merge branch 'feature_distributeCache' of https://github.com/EngRajabi/Ocelot into EngRajabi-feature_distributeCache
2 parents c004c43 + adffb1e commit b4c29fc

File tree

3 files changed

+162
-2
lines changed

3 files changed

+162
-2
lines changed

src/Ocelot/Cache/AspMemoryCache.cs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Microsoft.Extensions.Caching.Distributed;
5+
using Microsoft.Extensions.Caching.Memory;
6+
7+
namespace Ocelot.Cache
8+
{
9+
public class AspMemoryCache<T> : IOcelotCache<T>
10+
{
11+
private readonly IMemoryCache _memoryCache;
12+
private readonly Dictionary<string, List<string>> _regions;
13+
14+
public AspMemoryCache(IMemoryCache memoryCache)
15+
{
16+
_memoryCache = memoryCache;
17+
_regions = new Dictionary<string, List<string>>();
18+
}
19+
20+
public void Add(string key, T value, TimeSpan ttl, string region)
21+
{
22+
if (ttl.TotalMilliseconds <= 0)
23+
return;
24+
25+
_memoryCache.Set(key, value, ttl);
26+
27+
SetRegion(region, key);
28+
}
29+
30+
public T Get(string key, string region)
31+
{
32+
_memoryCache.TryGetValue<T>(key, out T value);
33+
34+
return value;
35+
}
36+
37+
public void ClearRegion(string region)
38+
{
39+
if (_regions.ContainsKey(region))
40+
{
41+
var keys = _regions[region];
42+
foreach (var key in keys)
43+
{
44+
_memoryCache.Remove(key);
45+
}
46+
}
47+
}
48+
49+
public void AddAndDelete(string key, T value, TimeSpan ttl, string region)
50+
{
51+
if (_memoryCache.TryGetValue(key, out object oldValue))
52+
_memoryCache.Remove(key);
53+
54+
Add(key, value, ttl, region);
55+
}
56+
57+
private void SetRegion(string region, string key)
58+
{
59+
if (_regions.ContainsKey(region))
60+
{
61+
var current = _regions[region];
62+
if (!current.Contains(key))
63+
{
64+
current.Add(key);
65+
}
66+
}
67+
else
68+
{
69+
_regions.Add(region, new List<string> { key });
70+
}
71+
}
72+
}
73+
}

src/Ocelot/DependencyInjection/OcelotBuilder.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,12 @@ public OcelotBuilder(IServiceCollection services, IConfiguration configurationRo
5858
Services = services;
5959
Services.Configure<FileConfiguration>(configurationRoot);
6060

61-
Services.TryAddSingleton<IOcelotCache<FileConfiguration>, InMemoryCache<FileConfiguration>>();
62-
Services.TryAddSingleton<IOcelotCache<CachedResponse>, InMemoryCache<CachedResponse>>();
61+
//Services.TryAddSingleton<IOcelotCache<FileConfiguration>, InMemoryCache<FileConfiguration>>();
62+
//Services.TryAddSingleton<IOcelotCache<CachedResponse>, InMemoryCache<CachedResponse>>();
63+
Services.TryAddSingleton<IOcelotCache<FileConfiguration>, AspMemoryCache<FileConfiguration>>();
64+
Services.TryAddSingleton<IOcelotCache<CachedResponse>, AspMemoryCache<CachedResponse>>();
65+
66+
6367
Services.TryAddSingleton<IHttpResponseHeaderReplacer, HttpResponseHeaderReplacer>();
6468
Services.TryAddSingleton<IHttpContextRequestHeaderReplacer, HttpContextRequestHeaderReplacer>();
6569
Services.TryAddSingleton<IHeaderFindAndReplaceCreator, HeaderFindAndReplaceCreator>();
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using Microsoft.Extensions.Caching.Memory;
2+
3+
namespace Ocelot.UnitTests.Cache
4+
{
5+
using Ocelot.Cache;
6+
using Shouldly;
7+
using System;
8+
using System.Threading;
9+
using Xunit;
10+
11+
public class AspMemoryCacheTests
12+
{
13+
private readonly AspMemoryCache<Fake> _cache;
14+
15+
public AspMemoryCacheTests()
16+
{
17+
_cache = new AspMemoryCache<Fake>(new MemoryCache(new MemoryCacheOptions()));
18+
}
19+
20+
[Fact]
21+
public void should_cache()
22+
{
23+
var fake = new Fake(1);
24+
_cache.Add("1", fake, TimeSpan.FromSeconds(100), "region");
25+
var result = _cache.Get("1", "region");
26+
result.ShouldBe(fake);
27+
fake.Value.ShouldBe(1);
28+
}
29+
30+
[Fact]
31+
public void should_add_and_delete()
32+
{
33+
var fake = new Fake(1);
34+
_cache.Add("1", fake, TimeSpan.FromSeconds(100), "region");
35+
var newFake = new Fake(1);
36+
_cache.AddAndDelete("1", newFake, TimeSpan.FromSeconds(100), "region");
37+
var result = _cache.Get("1", "region");
38+
result.ShouldBe(newFake);
39+
newFake.Value.ShouldBe(1);
40+
}
41+
42+
[Fact]
43+
public void should_clear_region()
44+
{
45+
var fake = new Fake(1);
46+
_cache.Add("1", fake, TimeSpan.FromSeconds(100), "region");
47+
_cache.ClearRegion("region");
48+
var result = _cache.Get("1", "region");
49+
result.ShouldBeNull();
50+
}
51+
52+
[Fact]
53+
public void should_clear_key_if_ttl_expired()
54+
{
55+
var fake = new Fake(1);
56+
_cache.Add("1", fake, TimeSpan.FromMilliseconds(50), "region");
57+
Thread.Sleep(200);
58+
var result = _cache.Get("1", "region");
59+
result.ShouldBeNull();
60+
}
61+
62+
[Theory]
63+
[InlineData(0)]
64+
[InlineData(-1)]
65+
public void should_not_add_to_cache_if_timespan_empty(int ttl)
66+
{
67+
var fake = new Fake(1);
68+
_cache.Add("1", fake, TimeSpan.FromSeconds(ttl), "region");
69+
var result = _cache.Get("1", "region");
70+
result.ShouldBeNull();
71+
}
72+
73+
private class Fake
74+
{
75+
public Fake(int value)
76+
{
77+
Value = value;
78+
}
79+
80+
public int Value { get; }
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)