mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 15:30:49 +08:00 
			
		
		
		
	Merge branch 'feature_distributeCache' of https://github.com/EngRajabi/Ocelot into EngRajabi-feature_distributeCache
This commit is contained in:
		
							
								
								
									
										73
									
								
								src/Ocelot/Cache/AspMemoryCache.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/Ocelot/Cache/AspMemoryCache.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using Microsoft.Extensions.Caching.Distributed;
 | 
			
		||||
using Microsoft.Extensions.Caching.Memory;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Cache
 | 
			
		||||
{
 | 
			
		||||
    public class AspMemoryCache<T> : IOcelotCache<T>
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IMemoryCache _memoryCache;
 | 
			
		||||
        private readonly Dictionary<string, List<string>> _regions;
 | 
			
		||||
 | 
			
		||||
        public AspMemoryCache(IMemoryCache memoryCache)
 | 
			
		||||
        {
 | 
			
		||||
            _memoryCache = memoryCache;
 | 
			
		||||
            _regions = new Dictionary<string, List<string>>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Add(string key, T value, TimeSpan ttl, string region)
 | 
			
		||||
        {
 | 
			
		||||
            if (ttl.TotalMilliseconds <= 0)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            _memoryCache.Set(key, value, ttl);
 | 
			
		||||
 | 
			
		||||
            SetRegion(region, key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public T Get(string key, string region)
 | 
			
		||||
        {
 | 
			
		||||
            _memoryCache.TryGetValue<T>(key, out T value);
 | 
			
		||||
 | 
			
		||||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ClearRegion(string region)
 | 
			
		||||
        {
 | 
			
		||||
            if (_regions.ContainsKey(region))
 | 
			
		||||
            {
 | 
			
		||||
                var keys = _regions[region];
 | 
			
		||||
                foreach (var key in keys)
 | 
			
		||||
                {
 | 
			
		||||
                    _memoryCache.Remove(key);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void AddAndDelete(string key, T value, TimeSpan ttl, string region)
 | 
			
		||||
        {
 | 
			
		||||
            if (_memoryCache.TryGetValue(key, out object oldValue))
 | 
			
		||||
                _memoryCache.Remove(key);
 | 
			
		||||
 | 
			
		||||
            Add(key, value, ttl, region);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void SetRegion(string region, string key)
 | 
			
		||||
        {
 | 
			
		||||
            if (_regions.ContainsKey(region))
 | 
			
		||||
            {
 | 
			
		||||
                var current = _regions[region];
 | 
			
		||||
                if (!current.Contains(key))
 | 
			
		||||
                {
 | 
			
		||||
                    current.Add(key);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                _regions.Add(region, new List<string> { key });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -58,8 +58,12 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            Services = services;
 | 
			
		||||
            Services.Configure<FileConfiguration>(configurationRoot);
 | 
			
		||||
 | 
			
		||||
            Services.TryAddSingleton<IOcelotCache<FileConfiguration>, InMemoryCache<FileConfiguration>>();
 | 
			
		||||
            Services.TryAddSingleton<IOcelotCache<CachedResponse>, InMemoryCache<CachedResponse>>();
 | 
			
		||||
            //Services.TryAddSingleton<IOcelotCache<FileConfiguration>, InMemoryCache<FileConfiguration>>();
 | 
			
		||||
            //Services.TryAddSingleton<IOcelotCache<CachedResponse>, InMemoryCache<CachedResponse>>();
 | 
			
		||||
            Services.TryAddSingleton<IOcelotCache<FileConfiguration>, AspMemoryCache<FileConfiguration>>();
 | 
			
		||||
            Services.TryAddSingleton<IOcelotCache<CachedResponse>, AspMemoryCache<CachedResponse>>();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            Services.TryAddSingleton<IHttpResponseHeaderReplacer, HttpResponseHeaderReplacer>();
 | 
			
		||||
            Services.TryAddSingleton<IHttpContextRequestHeaderReplacer, HttpContextRequestHeaderReplacer>();
 | 
			
		||||
            Services.TryAddSingleton<IHeaderFindAndReplaceCreator, HeaderFindAndReplaceCreator>();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										83
									
								
								test/Ocelot.UnitTests/Cache/AspMemoryCacheTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								test/Ocelot.UnitTests/Cache/AspMemoryCacheTests.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
using Microsoft.Extensions.Caching.Memory;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Cache
 | 
			
		||||
{
 | 
			
		||||
    using Ocelot.Cache;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Threading;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
 | 
			
		||||
    public class AspMemoryCacheTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly AspMemoryCache<Fake> _cache;
 | 
			
		||||
 | 
			
		||||
        public AspMemoryCacheTests()
 | 
			
		||||
        {
 | 
			
		||||
            _cache = new AspMemoryCache<Fake>(new MemoryCache(new MemoryCacheOptions()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_cache()
 | 
			
		||||
        {
 | 
			
		||||
            var fake = new Fake(1);
 | 
			
		||||
            _cache.Add("1", fake, TimeSpan.FromSeconds(100), "region");
 | 
			
		||||
            var result = _cache.Get("1", "region");
 | 
			
		||||
            result.ShouldBe(fake);
 | 
			
		||||
            fake.Value.ShouldBe(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_and_delete()
 | 
			
		||||
        {
 | 
			
		||||
            var fake = new Fake(1);
 | 
			
		||||
            _cache.Add("1", fake, TimeSpan.FromSeconds(100), "region");
 | 
			
		||||
            var newFake = new Fake(1);
 | 
			
		||||
            _cache.AddAndDelete("1", newFake, TimeSpan.FromSeconds(100), "region");
 | 
			
		||||
            var result = _cache.Get("1", "region");
 | 
			
		||||
            result.ShouldBe(newFake);
 | 
			
		||||
            newFake.Value.ShouldBe(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_clear_region()
 | 
			
		||||
        {
 | 
			
		||||
            var fake = new Fake(1);
 | 
			
		||||
            _cache.Add("1", fake, TimeSpan.FromSeconds(100), "region");
 | 
			
		||||
            _cache.ClearRegion("region");
 | 
			
		||||
            var result = _cache.Get("1", "region");
 | 
			
		||||
            result.ShouldBeNull();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_clear_key_if_ttl_expired()
 | 
			
		||||
        {
 | 
			
		||||
            var fake = new Fake(1);
 | 
			
		||||
            _cache.Add("1", fake, TimeSpan.FromMilliseconds(50), "region");
 | 
			
		||||
            Thread.Sleep(200);
 | 
			
		||||
            var result = _cache.Get("1", "region");
 | 
			
		||||
            result.ShouldBeNull();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Theory]
 | 
			
		||||
        [InlineData(0)]
 | 
			
		||||
        [InlineData(-1)]
 | 
			
		||||
        public void should_not_add_to_cache_if_timespan_empty(int ttl)
 | 
			
		||||
        {
 | 
			
		||||
            var fake = new Fake(1);
 | 
			
		||||
            _cache.Add("1", fake, TimeSpan.FromSeconds(ttl), "region");
 | 
			
		||||
            var result = _cache.Get("1", "region");
 | 
			
		||||
            result.ShouldBeNull();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private class Fake
 | 
			
		||||
        {
 | 
			
		||||
            public Fake(int value)
 | 
			
		||||
            {
 | 
			
		||||
                Value = value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public int Value { get; }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user