Add CacheOptions implement per cache item and global defaults. add tests, and fixed default cache name from item type name to item type full name.

pull/717/head
sailucheng 7 years ago
parent 19e745e762
commit fb8aacee89

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Serialization;
@ -17,6 +18,11 @@ namespace Volo.Abp.Caching
context.Services.AddDistributedMemoryCache();
context.Services.AddSingleton(typeof(IDistributedCache<>), typeof(DistributedCache<>));
context.Services.Configure<CacheOptions>(cacheOptions =>
{
cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromMinutes(20);
});
}
}
}

@ -1,4 +1,5 @@
using System;
using System.Linq;
using JetBrains.Annotations;
namespace Volo.Abp.Caching

@ -0,0 +1,25 @@
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp.Caching
{
public class CacheOptions
{
/// <summary>
/// Global Cache entry options.
/// </summary>
public DistributedCacheEntryOptions GlobalCacheEntryOptions { get; set; }
/// <summary>
/// List of all cache configurators.
/// (func argument:Name of cache)
/// </summary>
public List<Func<string, DistributedCacheEntryOptions>> CacheConfigurators { get; set; } //TODO list item use a configurator interface instead?
public CacheOptions()
{
CacheConfigurators = new List<Func<string, DistributedCacheEntryOptions>>();
GlobalCacheEntryOptions = new DistributedCacheEntryOptions();
}
}
}

@ -3,6 +3,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using Nito.AsyncEx;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Serialization;
@ -27,12 +28,17 @@ namespace Volo.Abp.Caching
protected AsyncLock AsyncLock { get; } = new AsyncLock();
protected DistributedCacheEntryOptions DefaultCacheOptions;
private readonly CacheOptions _cacheOption;
public DistributedCache(
IOptions<CacheOptions> cacheOption,
IDistributedCache cache,
ICancellationTokenProvider cancellationTokenProvider,
IObjectSerializer objectSerializer,
ICurrentTenant currentTenant)
{
_cacheOption = cacheOption.Value;
Cache = cache;
CancellationTokenProvider = cancellationTokenProvider;
ObjectSerializer = objectSerializer;
@ -64,7 +70,7 @@ namespace Volo.Abp.Caching
}
public TCacheItem GetOrAdd(
string key,
string key,
Func<TCacheItem> factory,
Func<DistributedCacheEntryOptions> optionsFactory = null)
{
@ -90,11 +96,12 @@ namespace Volo.Abp.Caching
}
public async Task<TCacheItem> GetOrAddAsync(
string key,
string key,
Func<Task<TCacheItem>> factory,
Func<DistributedCacheEntryOptions> optionsFactory = null,
Func<DistributedCacheEntryOptions> optionsFactory = null,
CancellationToken token = default)
{
token = CancellationTokenProvider.FallbackToProvider(token);
var value = await GetAsync(key, token);
if (value != null)
{
@ -121,7 +128,7 @@ namespace Volo.Abp.Caching
Cache.Set(
NormalizeKey(key),
ObjectSerializer.Serialize(value),
options ?? new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(20) } //TODO: implement per cache item and global defaults!!!
options ?? DefaultCacheOptions
);
}
@ -130,7 +137,7 @@ namespace Volo.Abp.Caching
return Cache.SetAsync(
NormalizeKey(key),
ObjectSerializer.Serialize(value),
options ?? new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(20) }, //TODO: implement per cache item and global defaults!!!
options ?? DefaultCacheOptions,
CancellationTokenProvider.FallbackToProvider(token)
);
}
@ -166,6 +173,18 @@ namespace Volo.Abp.Caching
return normalizedKey;
}
protected virtual DistributedCacheEntryOptions GetDefaultCacheEntryOptions()
{
foreach (var configure in _cacheOption.CacheConfigurators)
{
var options = configure.Invoke(CacheName);
if (options != null)
{
return options;
}
}
return _cacheOption.GlobalCacheEntryOptions;
}
protected virtual void SetDefaultOptions()
{
@ -175,10 +194,13 @@ namespace Volo.Abp.Caching
.OfType<CacheNameAttribute>()
.FirstOrDefault();
CacheName = cacheNameAttribute != null ? cacheNameAttribute.Name : typeof(TCacheItem).Name;
CacheName = cacheNameAttribute != null ? cacheNameAttribute.Name : typeof(TCacheItem).FullName;
//IgnoreMultiTenancy
IgnoreMultiTenancy = typeof(TCacheItem).IsDefined(typeof(IgnoreMultiTenancyAttribute), true);
//Configure default cache entry options
DefaultCacheOptions = GetDefaultCacheEntryOptions();
}
}
}

@ -1,10 +1,30 @@
using Volo.Abp.Modularity;
using Microsoft.Extensions.Caching.Distributed;
using System;
using Volo.Abp.Modularity;
namespace Volo.Abp.Caching
{
[DependsOn(typeof(AbpCachingModule))]
public class AbpCachingTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<CacheOptions>(option =>
{
option.CacheConfigurators.Add(cacheName =>
{
if (cacheName == typeof(Sail.Testing.Caching.PersonCacheItem).FullName)
{
return new DistributedCacheEntryOptions()
{
AbsoluteExpiration = DateTime.Parse("2099-01-01 12:00:00")
};
}
return null;
});
option.GlobalCacheEntryOptions.SetSlidingExpiration(TimeSpan.FromMinutes(20));
});
}
}
}

@ -0,0 +1,51 @@
using Microsoft.Extensions.Caching.Distributed;
using Shouldly;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace Volo.Abp.Caching
{
public class DistributedCache_ConfigureOptions_Test : AbpIntegratedTest<AbpCachingTestModule>
{
[Fact]
public async Task Configure_CacheOptions()
{
var personCache = GetRequiredService<IDistributedCache<Sail.Testing.Caching.PersonCacheItem>>();
var cacheKey = Guid.NewGuid().ToString();
//Get (not exists yet)
var cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
GetDefaultCachingOptions(personCache).SlidingExpiration.ShouldBeNull();
GetDefaultCachingOptions(personCache).AbsoluteExpiration.ShouldBe(new DateTime(2099, 1, 1, 12, 0, 0));
}
[Fact]
public async Task Default_CacheOptions_Should_Be_20_Mins()
{
var personCache = GetRequiredService<IDistributedCache<PersonCacheItem>>();
var cacheKey = Guid.NewGuid().ToString();
//Get (not exists yet)
var cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
GetDefaultCachingOptions(personCache).SlidingExpiration.ShouldBe(TimeSpan.FromMinutes(20));
}
private static DistributedCacheEntryOptions GetDefaultCachingOptions(object instance)
{
var defaultOptionsField = instance.GetType().GetTypeInfo().GetField("DefaultCacheOptions", BindingFlags.Instance | BindingFlags.NonPublic);
return (DistributedCacheEntryOptions)defaultOptionsField.GetValue(instance);
}
}
}

@ -72,5 +72,55 @@ namespace Volo.Abp.Caching
factoryExecuted.ShouldBeFalse();
cacheItem.Name.ShouldBe(personName);
}
[Fact]
public async Task SameClassName_But_DiffNamespace_Should_Not_Use_Same_Cache()
{
var personCache = GetRequiredService<IDistributedCache<PersonCacheItem>>();
var otherPersonCache = GetRequiredService<IDistributedCache<Sail.Testing.Caching.PersonCacheItem>>();
var cacheKey = Guid.NewGuid().ToString();
const string personName = "john nash";
//Get (not exists yet)
var cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
var cacheItem1 = await otherPersonCache.GetAsync(cacheKey);
cacheItem1.ShouldBeNull();
//Set
cacheItem = new PersonCacheItem(personName);
await personCache.SetAsync(cacheKey, cacheItem);
//Get (it should be available now, but otherPersonCache not exists now.
cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldNotBeNull();
cacheItem.Name.ShouldBe(personName);
cacheItem1 = await otherPersonCache.GetAsync(cacheKey);
cacheItem1.ShouldBeNull();
//set other person cache
cacheItem1 = new Sail.Testing.Caching.PersonCacheItem(personName);
await otherPersonCache.SetAsync(cacheKey, cacheItem1);
cacheItem1 = await otherPersonCache.GetAsync(cacheKey);
cacheItem1.ShouldNotBeNull();
cacheItem1.Name.ShouldBe(personName);
//Remove
await personCache.RemoveAsync(cacheKey);
//Get (not exists since removed)
cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
cacheItem1 = await otherPersonCache.GetAsync(cacheKey);
cacheItem1.ShouldNotBeNull();
}
}
}
}

@ -9,7 +9,25 @@ namespace Volo.Abp.Caching
private PersonCacheItem()
{
}
public PersonCacheItem(string name)
{
Name = name;
}
}
}
namespace Sail.Testing.Caching
{
[Serializable]
public class PersonCacheItem
{
public string Name { get; private set; }
private PersonCacheItem()
{
}
public PersonCacheItem(string name)

Loading…
Cancel
Save