From 38583ac0c1be0542bc83ee97e88c4722d9af8067 Mon Sep 17 00:00:00 2001 From: ahmetfarukulu Date: Wed, 13 Mar 2024 02:49:20 +0300 Subject: [PATCH 1/3] Tenant cache problem fixed --- .../Abp/MultiTenancy/TenantChangedEvent.cs | 16 ++++++++++++++++ .../Abp/TenantManagement/TenantAppService.cs | 10 +++++++++- .../TenantConfigurationCacheItemInvalidator.cs | 18 +++++++++++++----- .../Volo/Abp/TenantManagement/TenantManager.cs | 12 ++++++++---- 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantChangedEvent.cs diff --git a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantChangedEvent.cs b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantChangedEvent.cs new file mode 100644 index 0000000000..93c925827e --- /dev/null +++ b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantChangedEvent.cs @@ -0,0 +1,16 @@ +using System; + +namespace Volo.Abp.MultiTenancy; + +[Serializable] +public class TenantChangedEvent +{ + public Guid? Id { get; set; } + public string? NormalizedName { get; set; } + + public TenantChangedEvent(Guid? id = null, string? normalizedName = null) + { + Id = id; + NormalizedName = normalizedName; + } +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs index 46c85578f4..129a2a5433 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Data; using Volo.Abp.EventBus.Distributed; +using Volo.Abp.EventBus.Local; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectExtending; @@ -17,17 +18,20 @@ public class TenantAppService : TenantManagementAppServiceBase, ITenantAppServic protected ITenantRepository TenantRepository { get; } protected ITenantManager TenantManager { get; } protected IDistributedEventBus DistributedEventBus { get; } + protected ILocalEventBus LocalEventBus { get; } public TenantAppService( ITenantRepository tenantRepository, ITenantManager tenantManager, IDataSeeder dataSeeder, - IDistributedEventBus distributedEventBus) + IDistributedEventBus distributedEventBus, + ILocalEventBus localEventBus) { DataSeeder = dataSeeder; TenantRepository = tenantRepository; TenantManager = tenantManager; DistributedEventBus = distributedEventBus; + LocalEventBus = localEventBus; } public virtual async Task GetAsync(Guid id) @@ -132,6 +136,10 @@ public class TenantAppService : TenantManagementAppServiceBase, ITenantAppServic public virtual async Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString) { var tenant = await TenantRepository.GetAsync(id); + if (tenant.FindDefaultConnectionString() != defaultConnectionString) + { + await LocalEventBus.PublishAsync(new TenantChangedEvent(tenant.Id, tenant.NormalizedName)); + } tenant.SetDefaultConnectionString(defaultConnectionString); await TenantRepository.UpdateAsync(tenant); } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs index 09c1a9368f..1956ae47ab 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs @@ -4,14 +4,16 @@ using Volo.Abp.Caching; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Entities.Events; using Volo.Abp.EventBus; +using Volo.Abp.EventBus.Local; using Volo.Abp.MultiTenancy; namespace Volo.Abp.TenantManagement; - +[LocalEventHandlerOrder(-1)] public class TenantConfigurationCacheItemInvalidator : ILocalEventHandler>, - ILocalEventHandler>, ITransientDependency + ILocalEventHandler, + ITransientDependency { protected IDistributedCache Cache { get; } @@ -22,12 +24,17 @@ public class TenantConfigurationCacheItemInvalidator : public virtual async Task HandleEventAsync(EntityChangedEventData eventData) { + if (eventData is EntityCreatedEventData) + { + return; + } + await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.NormalizedName); } - public virtual async Task HandleEventAsync(EntityDeletedEventData eventData) + public virtual async Task HandleEventAsync(TenantChangedEvent eventData) { - await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.NormalizedName); + await ClearCacheAsync(eventData.Id, eventData.NormalizedName); } protected virtual async Task ClearCacheAsync(Guid? id, string normalizedName) @@ -37,6 +44,7 @@ public class TenantConfigurationCacheItemInvalidator : { TenantConfigurationCacheItem.CalculateCacheKey(id, null), TenantConfigurationCacheItem.CalculateCacheKey(null, normalizedName), + TenantConfigurationCacheItem.CalculateCacheKey(id, normalizedName), }); } -} +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs index 648e02d381..0f40cfdd0b 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Volo.Abp.Caching; using Volo.Abp.Domain.Services; +using Volo.Abp.EventBus.Local; using Volo.Abp.MultiTenancy; namespace Volo.Abp.TenantManagement; @@ -9,14 +10,17 @@ namespace Volo.Abp.TenantManagement; public class TenantManager : DomainService, ITenantManager { protected ITenantRepository TenantRepository { get; } - protected IDistributedCache Cache { get; } protected ITenantNormalizer TenantNormalizer { get; } + protected ILocalEventBus LocalEventBus { get; } - public TenantManager(ITenantRepository tenantRepository, IDistributedCache cache, ITenantNormalizer tenantNormalizer) + public TenantManager( + ITenantRepository tenantRepository, + ITenantNormalizer tenantNormalizer, + ILocalEventBus localEventBus) { TenantRepository = tenantRepository; - Cache = cache; TenantNormalizer = tenantNormalizer; + LocalEventBus = localEventBus; } public virtual async Task CreateAsync(string name) @@ -36,7 +40,7 @@ public class TenantManager : DomainService, ITenantManager var normalizedName = TenantNormalizer.NormalizeName(name); await ValidateNameAsync(normalizedName, tenant.Id); - await Cache.RemoveAsync(TenantConfigurationCacheItem.CalculateCacheKey(tenant.NormalizedName)); + await LocalEventBus.PublishAsync(new TenantChangedEvent(tenant.Id, tenant.NormalizedName)); tenant.SetName(name); tenant.SetNormalizedName(normalizedName); } From d4029cfe180481a350c285f675863b9bb0696c6b Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 14 Mar 2024 10:32:08 +0800 Subject: [PATCH 2/3] Cache_Should_Invalidator_When_Tenant_ConnectionString_Changed --- .../TenantAppService_Tests.cs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs index b797e05566..4288a66aea 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs @@ -2,6 +2,9 @@ using System.Linq; using System.Threading.Tasks; using Shouldly; +using Volo.Abp.Caching; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; using Xunit; namespace Volo.Abp.TenantManagement; @@ -9,10 +12,20 @@ namespace Volo.Abp.TenantManagement; public class TenantAppService_Tests : AbpTenantManagementApplicationTestBase { private readonly ITenantAppService _tenantAppService; + private readonly IUnitOfWorkManager _unitOfWorkManager; + private readonly IDistributedCache _cache; + private readonly ITenantStore _tenantStore; + private readonly ITenantRepository _tenantRepository; + private readonly ITenantNormalizer _tenantNormalizer; public TenantAppService_Tests() { _tenantAppService = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); + _cache = GetRequiredService>(); + _tenantStore = GetRequiredService(); + _tenantRepository = GetRequiredService(); + _tenantNormalizer = GetRequiredService(); } [Fact] @@ -108,4 +121,46 @@ public class TenantAppService_Tests : AbpTenantManagementApplicationTestBase dbContext.Tenants.Any(t => t.Id == acme.Id).ShouldBeFalse(); }); } + + [Fact] + public async Task Cache_Should_Invalidator_When_Tenant_ConnectionString_Changed() + { + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); + + // UpdateDefaultConnectionStringAsync + + // FindAsync will cache tenant. + await _tenantStore.FindAsync(acme.Id); + await _tenantStore.FindAsync(acme.NormalizedName); + + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldNotBeNull(); + + using (var uow = _unitOfWorkManager.Begin(requiresNew: true)) + { + await _tenantAppService.UpdateDefaultConnectionStringAsync(acme.Id, Guid.NewGuid().ToString()); + await uow.CompleteAsync(); + } + + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldBeNull(); + + // DeleteDefaultConnectionStringAsync + + // FindAsync will cache tenant. + await _tenantStore.FindAsync(acme.Id); + await _tenantStore.FindAsync(acme.NormalizedName); + + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldNotBeNull(); + + using (var uow = _unitOfWorkManager.Begin(requiresNew: true)) + { + await _tenantAppService.DeleteDefaultConnectionStringAsync(acme.Id); + await uow.CompleteAsync(); + } + + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldBeNull(); + } } From 3ea7f9aa24429d0e381c6cb0a41eb3bce8f3b5a3 Mon Sep 17 00:00:00 2001 From: ahmetfarukulu Date: Thu, 14 Mar 2024 12:23:20 +0300 Subject: [PATCH 3/3] TenantAppService.DeleteDefaultConnectionStringAsync fixed --- .../Volo/Abp/TenantManagement/TenantAppService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs index 129a2a5433..e902482c43 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs @@ -149,6 +149,7 @@ public class TenantAppService : TenantManagementAppServiceBase, ITenantAppServic { var tenant = await TenantRepository.GetAsync(id); tenant.RemoveDefaultConnectionString(); + await LocalEventBus.PublishAsync(new TenantChangedEvent(tenant.Id, tenant.NormalizedName)); await TenantRepository.UpdateAsync(tenant); } }