Browse Source

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
commit
fb8aacee89
  1. 6
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs
  2. 1
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheNameAttribute.cs
  3. 25
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs
  4. 34
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
  5. 22
      framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/AbpCachingTestModule.cs
  6. 51
      framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/DistributedCache_ConfigureOptions_Test.cs
  7. 52
      framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/DistributedCache_Tests.cs
  8. 20
      framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/PersonCacheItem.cs

6
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs

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

1
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheNameAttribute.cs

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

25
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs

@ -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();
}
}
}

34
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs

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

22
framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/AbpCachingTestModule.cs

@ -1,10 +1,30 @@
using Volo.Abp.Modularity; using Microsoft.Extensions.Caching.Distributed;
using System;
using Volo.Abp.Modularity;
namespace Volo.Abp.Caching namespace Volo.Abp.Caching
{ {
[DependsOn(typeof(AbpCachingModule))] [DependsOn(typeof(AbpCachingModule))]
public class AbpCachingTestModule : AbpModule 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));
});
}
} }
} }

51
framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/DistributedCache_ConfigureOptions_Test.cs

@ -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);
}
}
}

52
framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/DistributedCache_Tests.cs

@ -72,5 +72,55 @@ namespace Volo.Abp.Caching
factoryExecuted.ShouldBeFalse(); factoryExecuted.ShouldBeFalse();
cacheItem.Name.ShouldBe(personName); 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();
}
} }
} }

20
framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/PersonCacheItem.cs

@ -9,7 +9,25 @@ namespace Volo.Abp.Caching
private PersonCacheItem() 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) public PersonCacheItem(string name)

Loading…
Cancel
Save