using Abp; using Abp.Domain.Repositories; using Abp.Domain.Uow; using Abp.Events.Bus.Entities; using Abp.Events.Bus.Handlers; using Abp.Runtime.Caching; using Abp.Runtime.Security; using VberZero.BaseSystem.MultiTenancy; namespace VberZero.MultiTenancy; public class TenantCache : ITenantCache, IEventHandler> { private readonly ICacheManager _cacheManager; private readonly IRepository _tenantRepository; private readonly IUnitOfWorkManager _unitOfWorkManager; public TenantCache( ICacheManager cacheManager, IRepository tenantRepository, IUnitOfWorkManager unitOfWorkManager) { _cacheManager = cacheManager; _tenantRepository = tenantRepository; _unitOfWorkManager = unitOfWorkManager; } public virtual TenantCacheItem Get(int tenantId) { var cacheItem = GetOrNull(tenantId); if (cacheItem == null) { throw new AbpException("There is no tenant with given id: " + tenantId); } return cacheItem; } public virtual TenantCacheItem Get(string tenancyName) { var cacheItem = GetOrNull(tenancyName); if (cacheItem == null) { throw new AbpException("There is no tenant with given tenancy name: " + tenancyName); } return cacheItem; } public virtual TenantCacheItem GetOrNull(string tenancyName) { var tenantId = _cacheManager .GetTenantByNameCache() .Get( tenancyName.ToLowerInvariant(), () => GetTenantOrNull(tenancyName).Id ); if (tenantId == null) { return null; } return Get(tenantId.Value); } public TenantCacheItem GetOrNull(int tenantId) { return _cacheManager .GetTenantCache()! .Get( tenantId, () => { var tenant = GetTenantOrNull(tenantId); if (tenant == null) { return null; } return CreateTenantCacheItem(tenant); } ); } public virtual async Task GetAsync(int tenantId) { var cacheItem = await GetOrNullAsync(tenantId); if (cacheItem == null) { throw new AbpException("There is no tenant with given id: " + tenantId); } return cacheItem; } public virtual async Task GetAsync(string tenancyName) { var cacheItem = await GetOrNullAsync(tenancyName); if (cacheItem == null) { throw new AbpException("There is no tenant with given tenancy name: " + tenancyName); } return cacheItem; } public virtual async Task GetOrNullAsync(string tenancyName) { var tenantId = await _cacheManager .GetTenantByNameCache() .GetAsync( tenancyName.ToLowerInvariant(), async _ => (await GetTenantOrNullAsync(tenancyName)).Id ); if (tenantId == null) { return null; } return await GetAsync(tenantId.Value); } public virtual async Task GetOrNullAsync(int tenantId) { return await _cacheManager .GetTenantCache() .GetAsync( tenantId, async _ => { var tenant = await GetTenantOrNullAsync(tenantId); if (tenant == null) { return null; } return CreateTenantCacheItem(tenant); } ); } protected virtual TenantCacheItem CreateTenantCacheItem(Tenant tenant) { return new TenantCacheItem { Id = tenant.Id, Name = tenant.Name, TenancyName = tenant.TenancyName, //EditionId = tenant.EditionId, ConnectionString = SimpleStringCipher.Instance.Decrypt(tenant.ConnectionString), IsActive = tenant.IsActive }; } protected virtual Tenant GetTenantOrNull(int tenantId) { return _unitOfWorkManager.WithUnitOfWork(() => { using (_unitOfWorkManager.Current.SetTenantId(null)) { return _tenantRepository.FirstOrDefault(tenantId); } }); } protected virtual Tenant GetTenantOrNull(string tenancyName) { return _unitOfWorkManager.WithUnitOfWork(() => { using (_unitOfWorkManager.Current.SetTenantId(null)) { return _tenantRepository.FirstOrDefault(t => t.TenancyName == tenancyName); } }); } protected virtual async Task GetTenantOrNullAsync(int tenantId) { return await _unitOfWorkManager.WithUnitOfWorkAsync(async () => { using (_unitOfWorkManager.Current.SetTenantId(null)) { return await _tenantRepository.FirstOrDefaultAsync(tenantId); } }); } protected virtual async Task GetTenantOrNullAsync(string tenancyName) { return await _unitOfWorkManager.WithUnitOfWorkAsync(async () => { using (_unitOfWorkManager.Current.SetTenantId(null)) { return await _tenantRepository.FirstOrDefaultAsync(t => t.TenancyName == tenancyName); } }); } public virtual void HandleEvent(EntityChangedEventData eventData) { var existingCacheItem = _cacheManager.GetTenantCache().GetOrDefault(eventData.Entity.Id); _cacheManager .GetTenantByNameCache() .Remove( existingCacheItem != null ? existingCacheItem.TenancyName.ToLowerInvariant() : eventData.Entity.TenancyName.ToLowerInvariant() ); _cacheManager .GetTenantCache() .Remove(eventData.Entity.Id); } }