mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:42:50 +08:00
working on region clearing cache, if using cachemanager back plance this would clear all servers in cluster
This commit is contained in:
parent
26e7621798
commit
239dcfb6bd
@ -1,11 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ocelot.Cache
|
namespace Ocelot.Cache
|
||||||
{
|
{
|
||||||
public interface IOcelotCache<T>
|
public interface IOcelotCache<T>
|
||||||
{
|
{
|
||||||
void Add(string key, T value, TimeSpan ttl);
|
void Add(string key, T value, TimeSpan ttl, string region);
|
||||||
void AddAndDelete(string key, T value, TimeSpan ttl);
|
void AddAndDelete(string key, T value, TimeSpan ttl, string region);
|
||||||
T Get(string key);
|
T Get(string key);
|
||||||
|
void ClearRegion(string region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,9 @@ namespace Ocelot.Cache.Middleware
|
|||||||
|
|
||||||
var response = HttpResponseMessage;
|
var response = HttpResponseMessage;
|
||||||
|
|
||||||
_outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.FileCacheOptions.TtlSeconds));
|
var region = $"{DownstreamRoute.ReRoute.UpstreamHttpMethod}-{DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}";
|
||||||
|
|
||||||
|
_outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.FileCacheOptions.TtlSeconds), region);
|
||||||
|
|
||||||
_logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey);
|
_logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using CacheManager.Core;
|
using CacheManager.Core;
|
||||||
|
|
||||||
namespace Ocelot.Cache
|
namespace Ocelot.Cache
|
||||||
@ -6,18 +8,21 @@ namespace Ocelot.Cache
|
|||||||
public class OcelotCacheManagerCache<T> : IOcelotCache<T>
|
public class OcelotCacheManagerCache<T> : IOcelotCache<T>
|
||||||
{
|
{
|
||||||
private readonly ICacheManager<T> _cacheManager;
|
private readonly ICacheManager<T> _cacheManager;
|
||||||
|
private HashSet<string> _keys;
|
||||||
|
|
||||||
public OcelotCacheManagerCache(ICacheManager<T> cacheManager)
|
public OcelotCacheManagerCache(ICacheManager<T> cacheManager)
|
||||||
{
|
{
|
||||||
_cacheManager = cacheManager;
|
_cacheManager = cacheManager;
|
||||||
|
_keys = new HashSet<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(string key, T value, TimeSpan ttl)
|
public void Add(string key, T value, TimeSpan ttl, string region)
|
||||||
{
|
{
|
||||||
_cacheManager.Add(new CacheItem<T>(key, value, ExpirationMode.Absolute, ttl));
|
_cacheManager.Add(new CacheItem<T>(key, region, value, ExpirationMode.Absolute, ttl));
|
||||||
|
_keys.Add(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddAndDelete(string key, T value, TimeSpan ttl)
|
public void AddAndDelete(string key, T value, TimeSpan ttl, string region)
|
||||||
{
|
{
|
||||||
var exists = _cacheManager.Get(key);
|
var exists = _cacheManager.Get(key);
|
||||||
|
|
||||||
@ -26,12 +31,17 @@ namespace Ocelot.Cache
|
|||||||
_cacheManager.Remove(key);
|
_cacheManager.Remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cacheManager.Add(new CacheItem<T>(key, value, ExpirationMode.Absolute, ttl));
|
Add(key, value, ttl, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T Get(string key)
|
public T Get(string key)
|
||||||
{
|
{
|
||||||
return _cacheManager.Get<T>(key);
|
return _cacheManager.Get<T>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearRegion(string region)
|
||||||
|
{
|
||||||
|
_cacheManager.ClearRegion(region);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -68,7 +68,7 @@ namespace Ocelot.Configuration.Repository
|
|||||||
|
|
||||||
if (result.Response)
|
if (result.Response)
|
||||||
{
|
{
|
||||||
_cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3));
|
_cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), "OcelotConfiguration");
|
||||||
|
|
||||||
return new OkResponse();
|
return new OkResponse();
|
||||||
}
|
}
|
||||||
|
33
src/Ocelot/Controllers/OutputCacheController.cs
Normal file
33
src/Ocelot/Controllers/OutputCacheController.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Ocelot.Cache;
|
||||||
|
|
||||||
|
namespace Ocelot.Controllers
|
||||||
|
{
|
||||||
|
[Authorize]
|
||||||
|
[Route("cache")]
|
||||||
|
public class OutputCacheController : Controller
|
||||||
|
{
|
||||||
|
private IOcelotCache<HttpResponseMessage> _cache;
|
||||||
|
|
||||||
|
public OutputCacheController(IOcelotCache<HttpResponseMessage> cache)
|
||||||
|
{
|
||||||
|
_cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult Get()
|
||||||
|
{
|
||||||
|
return new NotFoundResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete]
|
||||||
|
[Route("{region}")]
|
||||||
|
public IActionResult Delete(string region)
|
||||||
|
{
|
||||||
|
_cache.ClearRegion(region);
|
||||||
|
return new NoContentResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using CacheManager.Core;
|
using CacheManager.Core;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Cache;
|
using Ocelot.Cache;
|
||||||
@ -16,12 +17,14 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
private string _value;
|
private string _value;
|
||||||
private string _resultGet;
|
private string _resultGet;
|
||||||
private TimeSpan _ttlSeconds;
|
private TimeSpan _ttlSeconds;
|
||||||
|
private List<string> _resultKeys;
|
||||||
|
|
||||||
public CacheManagerCacheTests()
|
public CacheManagerCacheTests()
|
||||||
{
|
{
|
||||||
_mockCacheManager = new Mock<ICacheManager<string>>();
|
_mockCacheManager = new Mock<ICacheManager<string>>();
|
||||||
_ocelotOcelotCacheManager = new OcelotCacheManagerCache<string>(_mockCacheManager.Object);
|
_ocelotOcelotCacheManager = new OcelotCacheManagerCache<string>(_mockCacheManager.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_get_from_cache()
|
public void should_get_from_cache()
|
||||||
{
|
{
|
||||||
@ -29,7 +32,6 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
.When(x => x.WhenIGetFromTheCache())
|
.When(x => x.WhenIGetFromTheCache())
|
||||||
.Then(x => x.ThenTheResultIs("someValue"))
|
.Then(x => x.ThenTheResultIs("someValue"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -40,13 +42,37 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_delete_key_from_cache()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheFollowingRegion("fookey"))
|
||||||
|
.When(_ => WhenIDeleteTheRegion("fookey"))
|
||||||
|
.Then(_ => ThenTheRegionIsDeleted("fookey"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIDeleteTheRegion(string region)
|
||||||
|
{
|
||||||
|
_ocelotOcelotCacheManager.ClearRegion(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheRegionIsDeleted(string region)
|
||||||
|
{
|
||||||
|
_mockCacheManager
|
||||||
|
.Verify(x => x.ClearRegion(region), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheFollowingRegion(string key)
|
||||||
|
{
|
||||||
|
_ocelotOcelotCacheManager.Add(key, "doesnt matter", TimeSpan.FromSeconds(10), "region");
|
||||||
|
}
|
||||||
|
|
||||||
private void WhenIAddToTheCache(string key, string value, TimeSpan ttlSeconds)
|
private void WhenIAddToTheCache(string key, string value, TimeSpan ttlSeconds)
|
||||||
{
|
{
|
||||||
_key = key;
|
_key = key;
|
||||||
_value = value;
|
_value = value;
|
||||||
_ttlSeconds = ttlSeconds;
|
_ttlSeconds = ttlSeconds;
|
||||||
|
_ocelotOcelotCacheManager.Add(_key, _value, _ttlSeconds, "region");
|
||||||
_ocelotOcelotCacheManager.Add(_key, _value, _ttlSeconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheCacheIsCalledCorrectly()
|
private void ThenTheCacheIsCalledCorrectly()
|
||||||
|
@ -124,7 +124,7 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
private void ThenTheCacheAddIsCalledCorrectly()
|
private void ThenTheCacheAddIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_cacheManager
|
_cacheManager
|
||||||
.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<HttpResponseMessage>(), It.IsAny<TimeSpan>()), Times.Once);
|
.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<HttpResponseMessage>(), It.IsAny<TimeSpan>(), It.IsAny<string>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenResponseIsNotCached()
|
private void GivenResponseIsNotCached()
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
using Xunit;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Ocelot.Controllers;
|
||||||
|
using System;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Cache;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Controllers
|
||||||
|
{
|
||||||
|
public class OutputCacheControllerTests
|
||||||
|
{
|
||||||
|
private OutputCacheController _controller;
|
||||||
|
private Mock<IOcelotCache<HttpResponseMessage>> _cache;
|
||||||
|
private IActionResult _result;
|
||||||
|
|
||||||
|
public OutputCacheControllerTests()
|
||||||
|
{
|
||||||
|
_cache = new Mock<IOcelotCache<HttpResponseMessage>>();
|
||||||
|
_controller = new OutputCacheController(_cache.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_get_all_keys_from_server()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheFollowingKeys(new List<string>{"b", "a"}))
|
||||||
|
.When(_ => WhenIGetTheKeys())
|
||||||
|
.Then(_ => ThenTheKeysAreReturned())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_delete_key()
|
||||||
|
{
|
||||||
|
this.When(_ => WhenIDeleteTheKey("a"))
|
||||||
|
.Then(_ => ThenTheKeyIsDeleted("a"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheKeyIsDeleted(string key)
|
||||||
|
{
|
||||||
|
_result.ShouldBeOfType<NoContentResult>();
|
||||||
|
_cache
|
||||||
|
.Verify(x => x.ClearRegion(key), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIDeleteTheKey(string key)
|
||||||
|
{
|
||||||
|
_result = _controller.Delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheFollowingKeys(List<string> keys)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIGetTheKeys()
|
||||||
|
{
|
||||||
|
_result = _controller.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheKeysAreReturned()
|
||||||
|
{
|
||||||
|
_result.ShouldBeOfType<OkObjectResult>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user