mirror of https://github.com/abpframework/abp.git
6 changed files with 236 additions and 33 deletions
@ -0,0 +1,36 @@ |
|||
using System; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.TenantManagement |
|||
{ |
|||
[Serializable] |
|||
[IgnoreMultiTenancy] |
|||
public class TenantCacheItem |
|||
{ |
|||
private const string CacheKeyFormat = "i:{0},n:{1}"; |
|||
|
|||
public TenantConfiguration Value { get; set; } |
|||
|
|||
public TenantCacheItem() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public TenantCacheItem(TenantConfiguration value) |
|||
{ |
|||
Value = value; |
|||
} |
|||
|
|||
public static string CalculateCacheKey(Guid? id, string name) |
|||
{ |
|||
if (id == null && name.IsNullOrWhiteSpace()) |
|||
{ |
|||
throw new AbpException("Both id and name can't be invalid."); |
|||
} |
|||
|
|||
return string.Format(CacheKeyFormat, |
|||
id?.ToString() ?? "null", |
|||
(name.IsNullOrWhiteSpace() ? "null" : name)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Entities.Events; |
|||
using Volo.Abp.EventBus; |
|||
|
|||
namespace Volo.Abp.TenantManagement |
|||
{ |
|||
public class TenantCacheItemInvalidator : ILocalEventHandler<EntityChangedEventData<Tenant>>, ITransientDependency |
|||
{ |
|||
protected IDistributedCache<TenantCacheItem> Cache { get; } |
|||
|
|||
public TenantCacheItemInvalidator(IDistributedCache<TenantCacheItem> cache) |
|||
{ |
|||
Cache = cache; |
|||
} |
|||
|
|||
public virtual async Task HandleEventAsync(EntityChangedEventData<Tenant> eventData) |
|||
{ |
|||
await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(eventData.Entity.Id, null)); |
|||
await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(null, eventData.Entity.Name)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,86 @@ |
|||
using System.Threading.Tasks; |
|||
using Shouldly; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.TenantManagement |
|||
{ |
|||
public class TenantCacheItemInvalidator_Tests : AbpTenantManagementDomainTestBase |
|||
{ |
|||
private readonly IDistributedCache<TenantCacheItem> _cache; |
|||
private readonly ITenantStore _tenantStore; |
|||
private readonly ITenantRepository _tenantRepository; |
|||
|
|||
public TenantCacheItemInvalidator_Tests() |
|||
{ |
|||
_cache = GetRequiredService<IDistributedCache<TenantCacheItem>>(); |
|||
_tenantStore = GetRequiredService<ITenantStore>(); |
|||
_tenantRepository = GetRequiredService<ITenantRepository>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Get_Tenant_Should_Cached() |
|||
{ |
|||
var acme = await _tenantRepository.FindByNameAsync("acme"); |
|||
acme.ShouldNotBeNull(); |
|||
|
|||
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); |
|||
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull(); |
|||
|
|||
await _tenantStore.FindAsync(acme.Id); |
|||
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); |
|||
|
|||
await _tenantStore.FindAsync(acme.Name); |
|||
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull(); |
|||
|
|||
|
|||
var volosoft = _tenantRepository.FindByName("volosoft"); |
|||
volosoft.ShouldNotBeNull(); |
|||
|
|||
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull(); |
|||
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull(); |
|||
|
|||
_tenantStore.Find(volosoft.Id); |
|||
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull(); |
|||
|
|||
_tenantStore.Find(volosoft.Name); |
|||
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Cache_Should_Invalidator_When_Tenant_Changed() |
|||
{ |
|||
var acme = await _tenantRepository.FindByNameAsync("acme"); |
|||
acme.ShouldNotBeNull(); |
|||
|
|||
// FindAsync will cache tenant.
|
|||
await _tenantStore.FindAsync(acme.Id); |
|||
await _tenantStore.FindAsync(acme.Name); |
|||
|
|||
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); |
|||
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull(); |
|||
|
|||
await _tenantRepository.DeleteAsync(acme); |
|||
|
|||
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); |
|||
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull(); |
|||
|
|||
|
|||
var volosoft = await _tenantRepository.FindByNameAsync("volosoft"); |
|||
volosoft.ShouldNotBeNull(); |
|||
|
|||
// Find will cache tenant.
|
|||
_tenantStore.Find(volosoft.Id); |
|||
_tenantStore.Find(volosoft.Name); |
|||
|
|||
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull(); |
|||
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull(); |
|||
|
|||
await _tenantRepository.DeleteAsync(volosoft); |
|||
|
|||
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull(); |
|||
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull(); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue