diff --git a/docs/en/Distributed-Event-Bus-Kafka-Integration.md b/docs/en/Distributed-Event-Bus-Kafka-Integration.md index 57a90c4b83..82e658f48d 100644 --- a/docs/en/Distributed-Event-Bus-Kafka-Integration.md +++ b/docs/en/Distributed-Event-Bus-Kafka-Integration.md @@ -110,7 +110,7 @@ You can use any of the [ClientConfig](https://docs.confluent.io/current/clients/ ### The Options Classes -`AbpRabbitMqOptions` and `AbpRabbitMqEventBusOptions` classes can be used to configure the connection strings and event bus options for the RabbitMQ. +`AbpKafkaOptions` and `AbpKafkaEventBusOptions` classes can be used to configure the connection strings and event bus options for the Kafka. You can configure this options inside the `ConfigureServices` of your [module](Module-Development-Basics.md). diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs index 469c0ad355..1f4b4ac871 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs @@ -5,6 +5,7 @@ namespace Volo.Abp.UI.Navigation; public class ApplicationMenuGroup { private string _displayName; + private string _elementId; /// /// Default value of a group item. @@ -32,7 +33,12 @@ public class ApplicationMenuGroup /// /// Can be used to render the element with a specific Id for DOM selections. /// - public string ElementId { get; set; } + public string ElementId { + get { return _elementId; } + set { + _elementId = NormalizeElementId(value); + } + } /// /// The Display order of the group. @@ -60,6 +66,11 @@ public class ApplicationMenuGroup return "MenuGroup_" + Name; } + private string NormalizeElementId(string elementId) + { + return elementId?.Replace(".", ""); + } + public override string ToString() { return $"[ApplicationMenuGroup] Name = {Name}"; diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs index dc1614e3e5..b9503874cc 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs @@ -8,6 +8,7 @@ namespace Volo.Abp.UI.Navigation; public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers { private string _displayName; + private string _elementId; /// /// Default value of a menu item. @@ -85,7 +86,12 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers /// Can be used to render the element with a specific Id for DOM selections. /// - public string ElementId { get; set; } + public string ElementId { + get { return _elementId; } + set { + _elementId = NormalizeElementId(value); + } + } /// /// Can be used to render the element with extra CSS classes. @@ -151,6 +157,11 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers() - .WaitAndRetryAsync(8, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt) * 10)) + .WaitAndRetryAsync( + 8, + retryAttempt => TimeSpan.FromSeconds( + RandomHelper.GetRandom( + (int)Math.Pow(2, retryAttempt) * 8, + (int)Math.Pow(2, retryAttempt) * 12) + ) + ) .ExecuteAsync(async _ => { try diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/StaticFeatureSaver.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/StaticFeatureSaver.cs index 5b3e581518..993e3ed32e 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/StaticFeatureSaver.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/StaticFeatureSaver.cs @@ -27,6 +27,8 @@ public class StaticFeatureSaver : IStaticFeatureSaver, ITransientDependency protected AbpFeatureOptions FeatureOptions { get; } protected ICancellationTokenProvider CancellationTokenProvider { get; } protected AbpDistributedCacheOptions CacheOptions { get; } + + protected IUnitOfWorkManager UnitOfWorkManager { get; } public StaticFeatureSaver( IStaticFeatureDefinitionStore staticStore, @@ -38,7 +40,8 @@ public class StaticFeatureSaver : IStaticFeatureSaver, ITransientDependency IApplicationInfoAccessor applicationInfoAccessor, IAbpDistributedLock distributedLock, IOptions featureManagementOptions, - ICancellationTokenProvider cancellationTokenProvider) + ICancellationTokenProvider cancellationTokenProvider, + IUnitOfWorkManager unitOfWorkManager) { StaticStore = staticStore; FeatureGroupRepository = featureGroupRepository; @@ -48,12 +51,12 @@ public class StaticFeatureSaver : IStaticFeatureSaver, ITransientDependency ApplicationInfoAccessor = applicationInfoAccessor; DistributedLock = distributedLock; CancellationTokenProvider = cancellationTokenProvider; + UnitOfWorkManager = unitOfWorkManager; FeatureOptions = featureManagementOptions.Value; CacheOptions = cacheOptions.Value; } - [UnitOfWork] - public virtual async Task SaveAsync() + public async Task SaveAsync() { await using var applicationLockHandle = await DistributedLock.TryAcquireAsync( GetApplicationDistributedLockKey() @@ -99,19 +102,40 @@ public class StaticFeatureSaver : IStaticFeatureSaver, ITransientDependency throw new AbpException("Could not acquire distributed lock for saving static features!"); } - var hasChangesInGroups = await UpdateChangedFeatureGroupsAsync(featureGroupRecords); - var hasChangesInFeatures = await UpdateChangedFeaturesAsync(featureRecords); - - if (hasChangesInGroups ||hasChangesInFeatures) + using (var unitOfWork = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true)) { - await Cache.SetStringAsync( - GetCommonStampCacheKey(), - Guid.NewGuid().ToString(), - new DistributedCacheEntryOptions { - SlidingExpiration = TimeSpan.FromDays(30) //TODO: Make it configurable? - }, - CancellationTokenProvider.Token - ); + try + { + var hasChangesInGroups = await UpdateChangedFeatureGroupsAsync(featureGroupRecords); + var hasChangesInFeatures = await UpdateChangedFeaturesAsync(featureRecords); + + if (hasChangesInGroups ||hasChangesInFeatures) + { + await Cache.SetStringAsync( + GetCommonStampCacheKey(), + Guid.NewGuid().ToString(), + new DistributedCacheEntryOptions { + SlidingExpiration = TimeSpan.FromDays(30) //TODO: Make it configurable? + }, + CancellationTokenProvider.Token + ); + } + } + catch + { + try + { + await unitOfWork.RollbackAsync(); + } + catch + { + /* ignored */ + } + + throw; + } + + await unitOfWork.CompleteAsync(); } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/AbpPermissionManagementDomainModule.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/AbpPermissionManagementDomainModule.cs index da96890997..0f40e3c039 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/AbpPermissionManagementDomainModule.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/AbpPermissionManagementDomainModule.cs @@ -118,7 +118,14 @@ public class AbpPermissionManagementDomainModule : AbpModule await Policy .Handle() - .WaitAndRetryAsync(8, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt) * 10)) + .WaitAndRetryAsync( + 8, + retryAttempt => TimeSpan.FromSeconds( + RandomHelper.GetRandom( + (int)Math.Pow(2, retryAttempt) * 8, + (int)Math.Pow(2, retryAttempt) * 12) + ) + ) .ExecuteAsync(async _ => { try diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/StaticPermissionSaver.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/StaticPermissionSaver.cs index 594f400a43..0bde8ebb0a 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/StaticPermissionSaver.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/StaticPermissionSaver.cs @@ -28,6 +28,8 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc protected ICancellationTokenProvider CancellationTokenProvider { get; } protected AbpDistributedCacheOptions CacheOptions { get; } + protected IUnitOfWorkManager UnitOfWorkManager { get; } + public StaticPermissionSaver( IStaticPermissionDefinitionStore staticStore, IPermissionGroupDefinitionRecordRepository permissionGroupRepository, @@ -38,8 +40,10 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc IApplicationInfoAccessor applicationInfoAccessor, IAbpDistributedLock distributedLock, IOptions permissionOptions, - ICancellationTokenProvider cancellationTokenProvider) + ICancellationTokenProvider cancellationTokenProvider, + IUnitOfWorkManager unitOfWorkManager) { + UnitOfWorkManager = unitOfWorkManager; StaticStore = staticStore; PermissionGroupRepository = permissionGroupRepository; PermissionRepository = permissionRepository; @@ -52,8 +56,7 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc CacheOptions = cacheOptions.Value; } - [UnitOfWork] - public virtual async Task SaveAsync() + public async Task SaveAsync() { await using var applicationLockHandle = await DistributedLock.TryAcquireAsync( GetApplicationDistributedLockKey() @@ -99,19 +102,40 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc throw new AbpException("Could not acquire distributed lock for saving static permissions!"); } - var hasChangesInGroups = await UpdateChangedPermissionGroupsAsync(permissionGroupRecords); - var hasChangesInPermissions = await UpdateChangedPermissionsAsync(permissionRecords); - - if (hasChangesInGroups ||hasChangesInPermissions) + using (var unitOfWork = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true)) { - await Cache.SetStringAsync( - GetCommonStampCacheKey(), - Guid.NewGuid().ToString(), - new DistributedCacheEntryOptions { - SlidingExpiration = TimeSpan.FromDays(30) //TODO: Make it configurable? - }, - CancellationTokenProvider.Token - ); + try + { + var hasChangesInGroups = await UpdateChangedPermissionGroupsAsync(permissionGroupRecords); + var hasChangesInPermissions = await UpdateChangedPermissionsAsync(permissionRecords); + + if (hasChangesInGroups || hasChangesInPermissions) + { + await Cache.SetStringAsync( + GetCommonStampCacheKey(), + Guid.NewGuid().ToString(), + new DistributedCacheEntryOptions { + SlidingExpiration = TimeSpan.FromDays(30) //TODO: Make it configurable? + }, + CancellationTokenProvider.Token + ); + } + } + catch + { + try + { + await unitOfWork.RollbackAsync(); + } + catch + { + /* ignored */ + } + + throw; + } + + await unitOfWork.CompleteAsync(); } } @@ -136,7 +160,8 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc foreach (var permissionGroupRecord in permissionGroupRecords) { - var permissionGroupRecordInDatabase = permissionGroupRecordsInDatabase.GetOrDefault(permissionGroupRecord.Name); + var permissionGroupRecordInDatabase = + permissionGroupRecordsInDatabase.GetOrDefault(permissionGroupRecord.Name); if (permissionGroupRecordInDatabase == null) { /* New group */ @@ -291,4 +316,4 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc .ToString() .ToMd5(); } -} +} \ No newline at end of file