diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Basket/Default.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Basket/Default.cshtml index 08870a7f..e4dad097 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Basket/Default.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Basket/Default.cshtml @@ -1,8 +1,11 @@ @using EShopOnAbp.Localization @using EShopOnAbp.PublicWeb.Components.Purchase @using Microsoft.Extensions.Localization +@using Microsoft.Extensions.Options +@using Volo.Abp.Http.Client @model EShopOnAbp.BasketService.Services.BasketDto @inject IStringLocalizer L +@inject IOptions options
@if (!Model.Items.Any()) @@ -31,7 +34,7 @@
@foreach (var item in Model.Items) { - string imageName = item.ImageName.IsNullOrEmpty() ? "/product-images/noimage.jpg" : $"/product-images/{item.ImageName}"; + string imageName = item.ImageName.IsNullOrEmpty() ? $"{options.Value.RemoteServices.Default.BaseUrl}product-images/noimage.jpg" : $"{options.Value.RemoteServices.Default.BaseUrl}product-images/{item.ImageName}"; var price = item.TotalPrice.ToString("0.00");
diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Toolbar/Cart/Default.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Toolbar/Cart/Default.cshtml index 5995e593..278186a5 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Toolbar/Cart/Default.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Toolbar/Cart/Default.cshtml @@ -1,7 +1,11 @@ @using EShopOnAbp.Localization @using Microsoft.AspNetCore.Mvc.Localization +@using Microsoft.Extensions.Options +@using Volo.Abp.Http.Client @inject IHtmlLocalizer L @model EShopOnAbp.BasketService.Services.BasketDto +@inject IOptions options +
-
+
} \ No newline at end of file diff --git a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/AdministrationServiceHttpApiHostModule.cs b/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/AdministrationServiceHttpApiHostModule.cs index cb17f630..9b349ff8 100644 --- a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/AdministrationServiceHttpApiHostModule.cs +++ b/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/AdministrationServiceHttpApiHostModule.cs @@ -103,6 +103,6 @@ public class AdministrationServiceHttpApiHostModule : AbpModule { await context.ServiceProvider .GetRequiredService() - .CheckAsync(); + .CheckAndApplyDatabaseMigrationsAsync(); } } \ No newline at end of file diff --git a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationChecker.cs b/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationChecker.cs index a683e8eb..615b3702 100644 --- a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationChecker.cs +++ b/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationChecker.cs @@ -1,8 +1,13 @@ using EShopOnAbp.AdministrationService.EntityFrameworkCore; -using System; using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.DistributedLocking; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; using Volo.Abp.Uow; namespace EShopOnAbp.AdministrationService.DbMigrations; @@ -10,17 +15,57 @@ namespace EShopOnAbp.AdministrationService.DbMigrations; public class AdministrationServiceDatabaseMigrationChecker : PendingEfCoreMigrationsChecker { + private readonly IPermissionDefinitionManager _permissionDefinitionManager; + private readonly IPermissionDataSeeder _permissionDataSeeder; + public AdministrationServiceDatabaseMigrationChecker( IUnitOfWorkManager unitOfWorkManager, IServiceProvider serviceProvider, ICurrentTenant currentTenant, - IDistributedEventBus distributedEventBus) + IDistributedEventBus distributedEventBus, + IAbpDistributedLock abpDistributedLock, + IPermissionDefinitionManager permissionDefinitionManager, + IPermissionDataSeeder permissionDataSeeder) : base( unitOfWorkManager, serviceProvider, currentTenant, distributedEventBus, + abpDistributedLock, AdministrationServiceDbProperties.ConnectionStringName) { + _permissionDefinitionManager = permissionDefinitionManager; + _permissionDataSeeder = permissionDataSeeder; + } + + public override async Task CheckAndApplyDatabaseMigrationsAsync() + { + await base.CheckAndApplyDatabaseMigrationsAsync(); + + await TryAsync(async () => await SeedDataAsync()); + } + + private async Task SeedDataAsync() + { + using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true)) + { + var multiTenancySide = MultiTenancySides.Host; + + var permissionNames = _permissionDefinitionManager + .GetPermissions() + .Where(p => p.MultiTenancySide.HasFlag(multiTenancySide)) + .Where(p => !p.Providers.Any() || + p.Providers.Contains(RolePermissionValueProvider.ProviderName)) + .Select(p => p.Name) + .ToArray(); + + await _permissionDataSeeder.SeedAsync( + RolePermissionValueProvider.ProviderName, + "admin", + permissionNames + ); + + await uow.CompleteAsync(); + } } } \ No newline at end of file diff --git a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationEventHandler.cs b/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationEventHandler.cs deleted file mode 100644 index a90f68de..00000000 --- a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationEventHandler.cs +++ /dev/null @@ -1,94 +0,0 @@ -using EShopOnAbp.AdministrationService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; -using Serilog; -using System; -using System.Linq; -using System.Threading.Tasks; -using Volo.Abp.Authorization.Permissions; -using Volo.Abp.Data; -using Volo.Abp.DistributedLocking; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.MultiTenancy; -using Volo.Abp.PermissionManagement; -using Volo.Abp.Uow; - -namespace EShopOnAbp.AdministrationService.DbMigrations; - -public class AdministrationServiceDatabaseMigrationEventHandler - : DatabaseEfCoreMigrationEventHandler, - IDistributedEventHandler -{ - private readonly IPermissionDefinitionManager _permissionDefinitionManager; - private readonly IPermissionDataSeeder _permissionDataSeeder; - - public AdministrationServiceDatabaseMigrationEventHandler( - ICurrentTenant currentTenant, - IUnitOfWorkManager unitOfWorkManager, - ITenantStore tenantStore, - IPermissionDefinitionManager permissionDefinitionManager, - IPermissionDataSeeder permissionDataSeeder, - IDistributedEventBus distributedEventBus, - IAbpDistributedLock distributedLockProvider - ) : base( - currentTenant, - unitOfWorkManager, - tenantStore, - distributedEventBus, - AdministrationServiceDbProperties.ConnectionStringName, - distributedLockProvider - ) - { - _permissionDefinitionManager = permissionDefinitionManager; - _permissionDataSeeder = permissionDataSeeder; - } - - public async Task HandleEventAsync(ApplyDatabaseMigrationsEto eventData) - { - if (eventData.DatabaseName != DatabaseName) - { - return; - } - - try - { - await using (var handle = await DistributedLockProvider.TryAcquireAsync(DatabaseName)) - { - Log.Information("AdministrationService acquired lock for db migration and seeding..."); - - if (handle != null) - { - await MigrateDatabaseSchemaAsync(); - await SeedDataAsync(); - } - } - } - catch (Exception ex) - { - await HandleErrorOnApplyDatabaseMigrationAsync(eventData, ex); - } - } - - private async Task SeedDataAsync() - { - using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true)) - { - var multiTenancySide = MultiTenancySides.Host; - - var permissionNames = _permissionDefinitionManager - .GetPermissions() - .Where(p => p.MultiTenancySide.HasFlag(multiTenancySide)) - .Where(p => !p.Providers.Any() || - p.Providers.Contains(RolePermissionValueProvider.ProviderName)) - .Select(p => p.Name) - .ToArray(); - - await _permissionDataSeeder.SeedAsync( - RolePermissionValueProvider.ProviderName, - "admin", - permissionNames - ); - - await uow.CompleteAsync(); - } - } -} \ No newline at end of file diff --git a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/CatalogServiceHttpApiHostModule.cs b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/CatalogServiceHttpApiHostModule.cs index 72c8cf92..f443513a 100644 --- a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/CatalogServiceHttpApiHostModule.cs +++ b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/CatalogServiceHttpApiHostModule.cs @@ -125,6 +125,6 @@ public class CatalogServiceHttpApiHostModule : AbpModule { await context.ServiceProvider .GetRequiredService() - .CheckAsync(); + .CheckAndApplyDatabaseMigrationsAsync(); } } \ No newline at end of file diff --git a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationChecker.cs b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationChecker.cs index 62551ec9..57be9d19 100644 --- a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationChecker.cs +++ b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationChecker.cs @@ -1,8 +1,8 @@ -using System; -using System.Threading.Tasks; -using EShopOnAbp.CatalogService.MongoDB; +using EShopOnAbp.CatalogService.MongoDB; using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; -using Volo.Abp.EventBus.Distributed; +using System; +using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; @@ -10,27 +10,19 @@ namespace EShopOnAbp.CatalogService.DbMigrations; public class CatalogServiceDatabaseMigrationChecker : PendingMongoDbMigrationsChecker { - private readonly ProductServiceDataSeeder _productServiceDataSeeder; - public CatalogServiceDatabaseMigrationChecker( IUnitOfWorkManager unitOfWorkManager, IServiceProvider serviceProvider, ICurrentTenant currentTenant, - IDistributedEventBus distributedEventBus, - ProductServiceDataSeeder productServiceDataSeeder) + IDataSeeder dataSeeder, + IAbpDistributedLock distributedLockProvider) : base( unitOfWorkManager, serviceProvider, currentTenant, - distributedEventBus, + dataSeeder, + distributedLockProvider, CatalogServiceDbProperties.ConnectionStringName) { - _productServiceDataSeeder = productServiceDataSeeder; - } - - public override async Task CheckAsync() - { - await base.CheckAsync(); - await _productServiceDataSeeder.SeedAsync(); } } \ No newline at end of file diff --git a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationEventHandler.cs b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationEventHandler.cs deleted file mode 100644 index adff87a9..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationEventHandler.cs +++ /dev/null @@ -1,66 +0,0 @@ -using EShopOnAbp.CatalogService.MongoDB; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.MongoDb; -using System; -using System.Threading.Tasks; -using Serilog; -using Volo.Abp.Data; -using Volo.Abp.DistributedLocking; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.MultiTenancy; -using Volo.Abp.Uow; - -namespace EShopOnAbp.CatalogService.DbMigrations; - -public class CatalogServiceDatabaseMigrationEventHandler - : DatabaseMongoDbMigrationEventHandler, - IDistributedEventHandler -{ - public CatalogServiceDatabaseMigrationEventHandler( - ICurrentTenant currentTenant, - IUnitOfWorkManager unitOfWorkManager, - ITenantStore tenantStore, - IDistributedEventBus distributedEventBus, - IServiceProvider serviceProvider, - IAbpDistributedLock distributedLockProvider - ) : base( - currentTenant, - unitOfWorkManager, - tenantStore, - distributedEventBus, - CatalogServiceDbProperties.ConnectionStringName, - serviceProvider, - distributedLockProvider) - { - } - - public async Task HandleEventAsync(ApplyDatabaseMigrationsEto eventData) - { - if (eventData.DatabaseName != DatabaseName) - { - return; - } - - if (eventData.TenantId != null) - { - return; - } - - try - { - Log.Information("CatalogService has acquired lock for db migration..."); - - await using (var handle = await DistributedLockProvider.TryAcquireAsync(DatabaseName)) - { - if (handle != null) - { - Log.Information("CatalogService is migrating database..."); - await MigrateDatabaseSchemaAsync(); - } - } - } - catch (Exception ex) - { - await HandleErrorOnApplyDatabaseMigrationAsync(eventData, ex); - } - } -} \ No newline at end of file diff --git a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/ProductServiceDataSeeder.cs b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/ProductServiceDataSeeder.cs index ae74bef7..b02bd34d 100644 --- a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/ProductServiceDataSeeder.cs +++ b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/ProductServiceDataSeeder.cs @@ -1,13 +1,14 @@ using System; using System.Threading.Tasks; using EShopOnAbp.CatalogService.Products; +using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; using Volo.Abp.Uow; namespace EShopOnAbp.CatalogService.DbMigrations; -public class ProductServiceDataSeeder : ITransientDependency +public class ProductServiceDataSeeder : IDataSeedContributor, ITransientDependency { private readonly ProductManager _productManager; private readonly IRepository _productRepository; @@ -20,8 +21,7 @@ public class ProductServiceDataSeeder : ITransientDependency _productManager = productManager; } - [UnitOfWork] - public virtual async Task SeedAsync() + public async Task SeedAsync(DataSeedContext context) { await AddProductsAsync(); } diff --git a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/ApplyDatabaseSeedsEto.cs b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/ApplyDatabaseSeedsEto.cs deleted file mode 100644 index 7dccb6a5..00000000 --- a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/ApplyDatabaseSeedsEto.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Volo.Abp.Domain.Entities.Events.Distributed; -using Volo.Abp.EventBus; - -namespace EShopOnAbp.IdentityService.DbMigrations; - -[EventName("abp.identity.apply_database_seeds")] -public class ApplyDatabaseSeedsEto : EtoBase -{ -} \ No newline at end of file diff --git a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/DataSeederEventHandler.cs b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/DataSeederEventHandler.cs deleted file mode 100644 index 8160d222..00000000 --- a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/DataSeederEventHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading.Tasks; -using Volo.Abp.Data; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; - -namespace EShopOnAbp.IdentityService.DbMigrations; - -public class DataSeederEventHandler : ILocalEventHandler, ITransientDependency -{ - protected IDataSeeder DataSeeder { get; } - - public DataSeederEventHandler(IDataSeeder dataSeeder) - { - DataSeeder = dataSeeder; - } - - public async Task HandleEventAsync(ApplyDatabaseSeedsEto eventData) - { - await DataSeeder.SeedAsync(); - } -} \ No newline at end of file diff --git a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationChecker.cs b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationChecker.cs index 29bdd116..b60910e0 100644 --- a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationChecker.cs +++ b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationChecker.cs @@ -6,38 +6,25 @@ using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Local; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; +using Volo.Abp.DistributedLocking; namespace EShopOnAbp.IdentityService.DbMigrations; public class IdentityServiceDatabaseMigrationChecker : PendingEfCoreMigrationsChecker { - protected ILocalEventBus LocalEventBus { get; } - public IdentityServiceDatabaseMigrationChecker( IUnitOfWorkManager unitOfWorkManager, IServiceProvider serviceProvider, ICurrentTenant currentTenant, IDistributedEventBus distributedEventBus, - ILocalEventBus localEventBus) + IAbpDistributedLock abpDistributedLock) : base( unitOfWorkManager, serviceProvider, currentTenant, distributedEventBus, + abpDistributedLock, IdentityServiceDbProperties.ConnectionStringName) { - LocalEventBus = localEventBus; - } - - public override async Task CheckAsync() - { - var isMigrationRequired = await base.CheckAsync(); - - if (!isMigrationRequired) - { - await LocalEventBus.PublishAsync(new ApplyDatabaseSeedsEto()); - } - - return isMigrationRequired; } } \ No newline at end of file diff --git a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationEventHandler.cs b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationEventHandler.cs deleted file mode 100644 index e879ea3a..00000000 --- a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationEventHandler.cs +++ /dev/null @@ -1,90 +0,0 @@ -using EShopOnAbp.IdentityService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; -using Serilog; -using System; -using System.Threading.Tasks; -using Volo.Abp.Data; -using Volo.Abp.DistributedLocking; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.EventBus.Local; -using Volo.Abp.Identity; -using Volo.Abp.MultiTenancy; -using Volo.Abp.Uow; - -namespace EShopOnAbp.IdentityService.DbMigrations; - -public class IdentityServiceDatabaseMigrationEventHandler - : DatabaseEfCoreMigrationEventHandler, - IDistributedEventHandler -{ - private readonly IIdentityDataSeeder _identityDataSeeder; - private readonly IdentityServerDataSeeder _identityServerDataSeeder; - private readonly ILocalEventBus _localEventBus; - - public IdentityServiceDatabaseMigrationEventHandler( - ICurrentTenant currentTenant, - IUnitOfWorkManager unitOfWorkManager, - ITenantStore tenantStore, - IIdentityDataSeeder identityDataSeeder, - IdentityServerDataSeeder identityServerDataSeeder, - IDistributedEventBus distributedEventBus, - ILocalEventBus localEventBus, - IAbpDistributedLock distributedLockProvider - ) : base( - currentTenant, - unitOfWorkManager, - tenantStore, - distributedEventBus, - IdentityServiceDbProperties.ConnectionStringName, - distributedLockProvider) - { - _identityDataSeeder = identityDataSeeder; - _identityServerDataSeeder = identityServerDataSeeder; - _localEventBus = localEventBus; - } - - public async Task HandleEventAsync(ApplyDatabaseMigrationsEto eventData) - { - if (eventData.DatabaseName != DatabaseName) - { - return; - } - - try - { - await using (var handle = await DistributedLockProvider.TryAcquireAsync(DatabaseName)) - { - Log.Information("IdentityService has acquired lock for db migration..."); - - if (handle != null) - { - Log.Information("IdentityService is migrating database..."); - await MigrateDatabaseSchemaAsync(); - Log.Information("IdentityService is seeding data..."); - await SeedDataAsync( - adminEmail: IdentityServiceDbProperties.DefaultAdminEmailAddress, - adminPassword: IdentityServiceDbProperties.DefaultAdminPassword - ); - } - } - - await _localEventBus.PublishAsync(new ApplyDatabaseSeedsEto()); - } - catch (Exception ex) - { - await HandleErrorOnApplyDatabaseMigrationAsync(eventData, ex); - } - } - - private async Task SeedDataAsync(string adminEmail, string adminPassword) - { - Log.Information($"Seeding IdentityServer data..."); - await _identityServerDataSeeder.SeedAsync(); - - Log.Information($"Seeding user data..."); - await _identityDataSeeder.SeedAsync( - adminEmail, - adminPassword - ); - } -} \ No newline at end of file diff --git a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/IdentityServiceHttpApiHostModule.cs b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/IdentityServiceHttpApiHostModule.cs index ddffb7a5..98ed74e0 100644 --- a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/IdentityServiceHttpApiHostModule.cs +++ b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/IdentityServiceHttpApiHostModule.cs @@ -100,6 +100,6 @@ public class IdentityServiceHttpApiHostModule : AbpModule { await context.ServiceProvider .GetRequiredService() - .CheckAsync(); + .CheckAndApplyDatabaseMigrationsAsync(); } } \ No newline at end of file diff --git a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationChecker.cs b/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationChecker.cs index 889464b0..b910af00 100644 --- a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationChecker.cs +++ b/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationChecker.cs @@ -4,6 +4,7 @@ using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; +using Volo.Abp.DistributedLocking; namespace EShopOnAbp.OrderingService.DbMigrations; @@ -14,12 +15,14 @@ public class OrderingServiceDatabaseMigrationChecker IUnitOfWorkManager unitOfWorkManager, IServiceProvider serviceProvider, ICurrentTenant currentTenant, - IDistributedEventBus distributedEventBus) + IDistributedEventBus distributedEventBus, + IAbpDistributedLock abpDistributedLock) : base( unitOfWorkManager, serviceProvider, currentTenant, distributedEventBus, + abpDistributedLock, OrderingServiceDbProperties.ConnectionStringName) { } diff --git a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationEventHandler.cs b/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationEventHandler.cs deleted file mode 100644 index a5b6672f..00000000 --- a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationEventHandler.cs +++ /dev/null @@ -1,70 +0,0 @@ -using EShopOnAbp.OrderingService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; -using System; -using System.Threading.Tasks; -using Serilog; -using Volo.Abp.Data; -using Volo.Abp.DistributedLocking; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.MultiTenancy; -using Volo.Abp.Uow; - -namespace EShopOnAbp.OrderingService.DbMigrations; - -public class OrderingServiceDatabaseMigrationEventHandler - : DatabaseEfCoreMigrationEventHandler, - IDistributedEventHandler -{ - private readonly IDataSeeder _dataSeeder; - - public OrderingServiceDatabaseMigrationEventHandler( - ICurrentTenant currentTenant, - IUnitOfWorkManager unitOfWorkManager, - ITenantStore tenantStore, - IDistributedEventBus distributedEventBus, - IDataSeeder dataSeeder, - IAbpDistributedLock distributedLockProvider) - : base( - currentTenant, - unitOfWorkManager, - tenantStore, - distributedEventBus, - OrderingServiceDbProperties.ConnectionStringName, - distributedLockProvider) - { - _dataSeeder = dataSeeder; - } - - public async Task HandleEventAsync(ApplyDatabaseMigrationsEto eventData) - { - if (eventData.DatabaseName != DatabaseName) - { - return; - } - - if (eventData.TenantId != null) - { - return; - } - - try - { - await using (var handle = await DistributedLockProvider.TryAcquireAsync(DatabaseName)) - { - Log.Information("OrderingService has acquired lock for db migration..."); - - if (handle != null) - { - Log.Information("OrderingService is migrating database..."); - await MigrateDatabaseSchemaAsync(); - Log.Information("OrderingService is seeding data..."); - await _dataSeeder.SeedAsync(); - } - } - } - catch (Exception ex) - { - await HandleErrorOnApplyDatabaseMigrationAsync(eventData, ex); - } - } -} \ No newline at end of file diff --git a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/OrderingServiceHttpApiHostModule.cs b/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/OrderingServiceHttpApiHostModule.cs index 29782aa7..04057038 100644 --- a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/OrderingServiceHttpApiHostModule.cs +++ b/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/OrderingServiceHttpApiHostModule.cs @@ -109,6 +109,6 @@ public class OrderingServiceHttpApiHostModule : AbpModule { await context.ServiceProvider .GetRequiredService() - .CheckAsync(); + .CheckAndApplyDatabaseMigrationsAsync(); } } \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationChecker.cs b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationChecker.cs index e5b9a962..5551fb38 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationChecker.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationChecker.cs @@ -4,6 +4,7 @@ using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; +using Volo.Abp.DistributedLocking; namespace EShopOnAbp.PaymentService.DbMigrations; @@ -14,12 +15,14 @@ public class PaymentServiceDatabaseMigrationChecker IUnitOfWorkManager unitOfWorkManager, IServiceProvider serviceProvider, ICurrentTenant currentTenant, - IDistributedEventBus distributedEventBus) + IDistributedEventBus distributedEventBus, + IAbpDistributedLock abpDistributedLock) : base( unitOfWorkManager, serviceProvider, currentTenant, distributedEventBus, + abpDistributedLock, PaymentServiceDbProperties.ConnectionStringName) { } diff --git a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationEventHandler.cs b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationEventHandler.cs deleted file mode 100644 index 5b59bd4d..00000000 --- a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationEventHandler.cs +++ /dev/null @@ -1,64 +0,0 @@ -using EShopOnAbp.PaymentService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; -using System; -using System.Threading.Tasks; -using Serilog; -using Volo.Abp.Data; -using Volo.Abp.DistributedLocking; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.MultiTenancy; -using Volo.Abp.Uow; - -namespace EShopOnAbp.PaymentService.DbMigrations; - -public class PaymentServiceDatabaseMigrationEventHandler - : DatabaseEfCoreMigrationEventHandler, - IDistributedEventHandler -{ - public PaymentServiceDatabaseMigrationEventHandler( - ICurrentTenant currentTenant, - IUnitOfWorkManager unitOfWorkManager, - ITenantStore tenantStore, - IDistributedEventBus distributedEventBus, - IAbpDistributedLock distributedLockProvider) - : base( - currentTenant, - unitOfWorkManager, - tenantStore, - distributedEventBus, - PaymentServiceDbProperties.ConnectionStringName, - distributedLockProvider) - { - } - - public async Task HandleEventAsync(ApplyDatabaseMigrationsEto eventData) - { - if (eventData.DatabaseName != DatabaseName) - { - return; - } - - if (eventData.TenantId != null) - { - return; - } - - try - { - Log.Information("PaymentService has acquired lock for db migration..."); - - await using (var handle = await DistributedLockProvider.TryAcquireAsync(DatabaseName)) - { - if (handle != null) - { - Log.Information("PaymentService is migrating database..."); - await MigrateDatabaseSchemaAsync(); - } - } - } - catch (Exception ex) - { - await HandleErrorOnApplyDatabaseMigrationAsync(eventData, ex); - } - } -} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/PaymentServiceHttpApiHostModule.cs b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/PaymentServiceHttpApiHostModule.cs index d51fbba3..f9af9d45 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/PaymentServiceHttpApiHostModule.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/PaymentServiceHttpApiHostModule.cs @@ -100,6 +100,6 @@ public class PaymentServiceHttpApiHostModule : AbpModule { await context.ServiceProvider .GetRequiredService() - .CheckAsync(); + .CheckAndApplyDatabaseMigrationsAsync(); } } \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/DatabaseMigrationEventHandlerBase.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/DatabaseMigrationEventHandlerBase.cs deleted file mode 100644 index dcaf6366..00000000 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/DatabaseMigrationEventHandlerBase.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Volo.Abp.DependencyInjection; - -namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; - -public abstract class DatabaseMigrationEventHandlerBase : ITransientDependency -{ -} \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/DatabaseEfCoreMigrationEventHandler.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/DatabaseEfCoreMigrationEventHandler.cs deleted file mode 100644 index 02719e9a..00000000 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/DatabaseEfCoreMigrationEventHandler.cs +++ /dev/null @@ -1,133 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Serilog; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.Data; -using Volo.Abp.DistributedLocking; -using Volo.Abp.Domain.Entities.Events.Distributed; -using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.MultiTenancy; -using Volo.Abp.Uow; - -namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; - -public abstract class DatabaseEfCoreMigrationEventHandler : DatabaseMigrationEventHandlerBase - where TDbContext : DbContext, IEfCoreDbContext -{ - protected const string TryCountPropertyName = "TryCount"; - protected const int MaxEventTryCount = 3; - protected ICurrentTenant CurrentTenant { get; } - protected IUnitOfWorkManager UnitOfWorkManager { get; } - protected ITenantStore TenantStore { get; } - protected IDistributedEventBus DistributedEventBus { get; } - protected ILogger> Logger { get; set; } - protected string DatabaseName { get; } - protected IAbpDistributedLock DistributedLockProvider { get; } - - protected DatabaseEfCoreMigrationEventHandler( - ICurrentTenant currentTenant, - IUnitOfWorkManager unitOfWorkManager, - ITenantStore tenantStore, - IDistributedEventBus distributedEventBus, - string databaseName, - IAbpDistributedLock distributedLockProvider - ) - { - CurrentTenant = currentTenant; - UnitOfWorkManager = unitOfWorkManager; - TenantStore = tenantStore; - DatabaseName = databaseName; - DistributedEventBus = distributedEventBus; - DistributedLockProvider = distributedLockProvider; - - Logger = NullLogger>.Instance; - } - - /// - /// Apply pending EF Core schema migrations to the database. - /// Returns true if any migration has applied. - /// - protected virtual async Task MigrateDatabaseSchemaAsync() - { - var result = false; - - using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) - { - async Task MigrateDatabaseSchemaWithDbContextAsync() - { - var dbContext = await uow.ServiceProvider - .GetRequiredService>() - .GetDbContextAsync(); - - if ((await dbContext.Database.GetPendingMigrationsAsync()).Any()) - { - await dbContext.Database.MigrateAsync(); - return true; - } - - return false; - } - - //Migrating the host database - Log.Information($"There is no tenant. Migrating {DatabaseName}..."); - result = await MigrateDatabaseSchemaWithDbContextAsync(); - - await uow.CompleteAsync(); - } - - return result; - } - - protected virtual async Task HandleErrorOnApplyDatabaseMigrationAsync( - ApplyDatabaseMigrationsEto eventData, - Exception exception) - { - var tryCount = IncrementEventTryCount(eventData); - if (tryCount <= MaxEventTryCount) - { - Log.Warning( - $"Could not apply database migrations. Re-queueing the operation. TenantId = {eventData.TenantId}, Database Name = {eventData.DatabaseName}."); - Log.Error(exception.ToString()); - - await Task.Delay(RandomHelper.GetRandom(5000, 15000)); - Log.Warning("Re publishing the event!"); - await DistributedEventBus.PublishAsync(eventData); - } - else - { - Log.Warning( - $"Could not apply database migrations. Canceling the operation. TenantId = {eventData.TenantId}, DatabaseName = {eventData.DatabaseName}."); - Log.Error(exception.ToString()); - } - } - - private static int GetEventTryCount(EtoBase eventData) - { - var tryCountAsString = eventData.Properties.GetOrDefault(TryCountPropertyName); - if (tryCountAsString.IsNullOrEmpty()) - { - return 0; - } - - return int.Parse(tryCountAsString); - } - - private static void SetEventTryCount(EtoBase eventData, int count) - { - eventData.Properties[TryCountPropertyName] = count.ToString(); - } - - private static int IncrementEventTryCount(EtoBase eventData) - { - var count = GetEventTryCount(eventData) + 1; - SetEventTryCount(eventData, count); - return count; - } -} \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/PendingEfCoreMigrationsChecker.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/PendingEfCoreMigrationsChecker.cs index beea6577..82bd596c 100644 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/PendingEfCoreMigrationsChecker.cs +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/PendingEfCoreMigrationsChecker.cs @@ -1,9 +1,11 @@ -using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Serilog; +using System; using System.Linq; using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; @@ -17,6 +19,7 @@ public abstract class PendingEfCoreMigrationsChecker : PendingMigrat protected IServiceProvider ServiceProvider { get; } protected ICurrentTenant CurrentTenant { get; } protected IDistributedEventBus DistributedEventBus { get; } + protected IAbpDistributedLock DistributedLockProvider { get; } protected string DatabaseName { get; } protected PendingEfCoreMigrationsChecker( @@ -24,44 +27,57 @@ public abstract class PendingEfCoreMigrationsChecker : PendingMigrat IServiceProvider serviceProvider, ICurrentTenant currentTenant, IDistributedEventBus distributedEventBus, + IAbpDistributedLock abpDistributedLock, string databaseName) { UnitOfWorkManager = unitOfWorkManager; ServiceProvider = serviceProvider; CurrentTenant = currentTenant; DistributedEventBus = distributedEventBus; + DistributedLockProvider = abpDistributedLock; DatabaseName = databaseName; } - public virtual async Task CheckAsync() + public virtual async Task CheckAndApplyDatabaseMigrationsAsync() { - var isMigrationRequired = false; + await TryAsync(LockAndApplyDatabaseMigrationsAsync); + } - using (CurrentTenant.Change(null)) + protected virtual async Task LockAndApplyDatabaseMigrationsAsync() + { + await using (var handle = await DistributedLockProvider.TryAcquireAsync("Migration_" + DatabaseName)) { - // Create database tables if needed - using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) + Log.Information($"Lock is acquired for db migration and seeding on database named: {DatabaseName}..."); + + if (handle is null) { - var pendingMigrations = await ServiceProvider - .GetRequiredService() - .Database - .GetPendingMigrationsAsync(); + Log.Information($"Handle is null because of the locking for : {DatabaseName}"); + return; + } - if (pendingMigrations.Any()) + using (CurrentTenant.Change(null)) + { + // Create database tables if needed + using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) { - await DistributedEventBus.PublishAsync( - new ApplyDatabaseMigrationsEto - { - DatabaseName = DatabaseName - } - ); - isMigrationRequired = true; + var dbContext = ServiceProvider.GetRequiredService(); + + var pendingMigrations = await dbContext + .Database + .GetPendingMigrationsAsync(); + + if (pendingMigrations.Any()) + { + await dbContext.Database.MigrateAsync(); + } + + await uow.CompleteAsync(); } - await uow.CompleteAsync(); + await ServiceProvider.GetRequiredService() + .SeedAsync(); } - - return isMigrationRequired; + Log.Information($"Lock is released for db migration and seeding on database named: {DatabaseName}..."); } } } \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/DatabaseMongoDbMigrationEventHandler.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/DatabaseMongoDbMigrationEventHandler.cs deleted file mode 100644 index 79784821..00000000 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/DatabaseMongoDbMigrationEventHandler.cs +++ /dev/null @@ -1,149 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using MongoDB.Driver; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.Data; -using Volo.Abp.DistributedLocking; -using Volo.Abp.Domain.Entities.Events.Distributed; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.MongoDB; -using Volo.Abp.MultiTenancy; -using Volo.Abp.Uow; - -namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.MongoDb; - -public abstract class DatabaseMongoDbMigrationEventHandler : DatabaseMigrationEventHandlerBase - where TDbContext : AbpMongoDbContext, IAbpMongoDbContext -{ - protected const string TryCountPropertyName = "TryCount"; - protected const int MaxEventTryCount = 3; - - protected ICurrentTenant CurrentTenant { get; } - protected IUnitOfWorkManager UnitOfWorkManager { get; } - protected ITenantStore TenantStore { get; } - protected IDistributedEventBus DistributedEventBus { get; } - protected ILogger> Logger { get; set; } - protected IServiceProvider ServiceProvider { get; } - protected string DatabaseName { get; } - protected IAbpDistributedLock DistributedLockProvider { get; } - - - protected DatabaseMongoDbMigrationEventHandler( - ICurrentTenant currentTenant, - IUnitOfWorkManager unitOfWorkManager, - ITenantStore tenantStore, - IDistributedEventBus distributedEventBus, - string databaseName, - IServiceProvider serviceProvider, - IAbpDistributedLock distributedLockProvider - ) - { - CurrentTenant = currentTenant; - UnitOfWorkManager = unitOfWorkManager; - TenantStore = tenantStore; - DatabaseName = databaseName; - ServiceProvider = serviceProvider; - DistributedEventBus = distributedEventBus; - DistributedLockProvider = distributedLockProvider; - - Logger = NullLogger>.Instance; - } - - /// - /// Apply pending EF Core schema migrations to the database. - /// Returns true if any migration has applied. - /// - protected virtual async Task MigrateDatabaseSchemaAsync() - { - var result = false; - - using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) - { - async Task MigrateDatabaseSchemaWithDbContextAsync() - { - var dbContexts = ServiceProvider.GetServices(); - var connectionStringResolver = ServiceProvider.GetRequiredService(); - - foreach (var dbContext in dbContexts) - { - var connectionString = - await connectionStringResolver.ResolveAsync( - ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType())); - if (connectionString.IsNullOrWhiteSpace()) - { - continue; - } - - var mongoUrl = new MongoUrl(connectionString); - var databaseName = mongoUrl.DatabaseName; - var client = new MongoClient(mongoUrl); - - if (databaseName.IsNullOrWhiteSpace()) - { - databaseName = ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType()); - } - - (dbContext as AbpMongoDbContext)?.InitializeCollections(client.GetDatabase(databaseName)); - } - - return true; - } - - //Migrating the host database - result = await MigrateDatabaseSchemaWithDbContextAsync(); - - await uow.CompleteAsync(); - } - - return result; - } - - protected virtual async Task HandleErrorOnApplyDatabaseMigrationAsync( - ApplyDatabaseMigrationsEto eventData, - Exception exception) - { - var tryCount = IncrementEventTryCount(eventData); - if (tryCount <= MaxEventTryCount) - { - Logger.LogWarning( - $"Could not apply database migrations. Re-queueing the operation. TenantId = {eventData.TenantId}, Database Name = {eventData.DatabaseName}."); - Logger.LogException(exception, LogLevel.Warning); - - await Task.Delay(RandomHelper.GetRandom(5000, 15000)); - await DistributedEventBus.PublishAsync(eventData); - } - else - { - Logger.LogError( - $"Could not apply database migrations. Canceling the operation. TenantId = {eventData.TenantId}, DatabaseName = {eventData.DatabaseName}."); - Logger.LogException(exception); - } - } - - private static int GetEventTryCount(EtoBase eventData) - { - var tryCountAsString = eventData.Properties.GetOrDefault(TryCountPropertyName); - if (tryCountAsString.IsNullOrEmpty()) - { - return 0; - } - - return int.Parse(tryCountAsString); - } - - private static void SetEventTryCount(EtoBase eventData, int count) - { - eventData.Properties[TryCountPropertyName] = count.ToString(); - } - - private static int IncrementEventTryCount(EtoBase eventData) - { - var count = GetEventTryCount(eventData) + 1; - SetEventTryCount(eventData, count); - return count; - } -} \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/PendingMongoDbMigrationsChecker.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/PendingMongoDbMigrationsChecker.cs index 61767f1f..ed8cb227 100644 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/PendingMongoDbMigrationsChecker.cs +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/PendingMongoDbMigrationsChecker.cs @@ -1,7 +1,10 @@ -using System; +using Microsoft.Extensions.DependencyInjection; +using MongoDB.Driver; +using Serilog; +using System; using System.Threading.Tasks; using Volo.Abp.Data; -using Volo.Abp.EventBus.Distributed; +using Volo.Abp.DistributedLocking; using Volo.Abp.MongoDB; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; @@ -14,39 +17,100 @@ public class PendingMongoDbMigrationsChecker : PendingMigrationsChec protected IUnitOfWorkManager UnitOfWorkManager { get; } protected IServiceProvider ServiceProvider { get; } protected ICurrentTenant CurrentTenant { get; } - protected IDistributedEventBus DistributedEventBus { get; } + protected IDataSeeder DataSeeder { get; } + protected IAbpDistributedLock DistributedLockProvider { get; } protected string DatabaseName { get; } protected PendingMongoDbMigrationsChecker( IUnitOfWorkManager unitOfWorkManager, IServiceProvider serviceProvider, ICurrentTenant currentTenant, - IDistributedEventBus distributedEventBus, + IDataSeeder dataSeeder, + IAbpDistributedLock distributedLockProvider, string databaseName) { UnitOfWorkManager = unitOfWorkManager; ServiceProvider = serviceProvider; CurrentTenant = currentTenant; - DistributedEventBus = distributedEventBus; + DataSeeder = dataSeeder; + DistributedLockProvider = distributedLockProvider; DatabaseName = databaseName; } - public virtual async Task CheckAsync() + public virtual async Task CheckAndApplyDatabaseMigrationsAsync() { - using (CurrentTenant.Change(null)) + await TryAsync(async () => + { + using (CurrentTenant.Change(null)) + { + // Create database tables if needed + using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) + { + await MigrateDatabaseSchemaAsync(); + + await DataSeeder.SeedAsync(); + + await uow.CompleteAsync(); + } + } + }); + } + + /// + /// Apply scheme update for MongoDB Database. + /// + protected virtual async Task MigrateDatabaseSchemaAsync() + { + var result = false; + await using (var handle = await DistributedLockProvider.TryAcquireAsync("Migration_" + DatabaseName)) { - // Create database tables if needed using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) { - await DistributedEventBus.PublishAsync( - new ApplyDatabaseMigrationsEto + Log.Information($"Lock is acquired for db migration and seeding on database named: {DatabaseName}..."); + + if (handle is null) + { + Log.Information($"Handle is null because of the locking for : {DatabaseName}"); + return false; + } + + async Task MigrateDatabaseSchemaWithDbContextAsync() + { + var dbContexts = ServiceProvider.GetServices(); + var connectionStringResolver = ServiceProvider.GetRequiredService(); + + foreach (var dbContext in dbContexts) { - DatabaseName = DatabaseName + var connectionString = + await connectionStringResolver.ResolveAsync( + ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType())); + if (connectionString.IsNullOrWhiteSpace()) + { + continue; + } + + var mongoUrl = new MongoUrl(connectionString); + var databaseName = mongoUrl.DatabaseName; + var client = new MongoClient(mongoUrl); + + if (databaseName.IsNullOrWhiteSpace()) + { + databaseName = ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType()); + } + + (dbContext as AbpMongoDbContext)?.InitializeCollections(client.GetDatabase(databaseName)); } - ); + + return true; + } + + //Migrating the host database + result = await MigrateDatabaseSchemaWithDbContextAsync(); await uow.CompleteAsync(); } + + return result; } } } \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/PendingMigrationsCheckerBase.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/PendingMigrationsCheckerBase.cs index 22d69b2d..8aac8078 100644 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/PendingMigrationsCheckerBase.cs +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/PendingMigrationsCheckerBase.cs @@ -1,7 +1,33 @@ -using Volo.Abp.DependencyInjection; +using Serilog; +using System; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; public abstract class PendingMigrationsCheckerBase : ITransientDependency { + public async Task TryAsync(Func task, int retryCount = 3) + { + try + { + await task(); + } + catch (Exception ex) + { + retryCount--; + + if (retryCount <= 0) + { + throw; + } + + Log.Warning($"{ex.GetType().Name} has been thrown. The operation will be tried {retryCount} times more. Exception:\n{ex.Message}"); + + await Task.Delay(RandomHelper.GetRandom(5000, 15000)); + + await TryAsync(task, retryCount); + } + } } \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbp.Shared.Hosting.Microservices.csproj b/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbp.Shared.Hosting.Microservices.csproj index 948da22e..8580e08f 100644 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbp.Shared.Hosting.Microservices.csproj +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbp.Shared.Hosting.Microservices.csproj @@ -9,10 +9,8 @@ - - @@ -21,6 +19,9 @@ + + + diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbpSharedHostingMicroservicesModule.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbpSharedHostingMicroservicesModule.cs index ad58eef3..e497d6d5 100644 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbpSharedHostingMicroservicesModule.cs +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbpSharedHostingMicroservicesModule.cs @@ -9,6 +9,7 @@ using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.BackgroundJobs.RabbitMQ; using Volo.Abp.Caching; using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.DistributedLocking; using Volo.Abp.EventBus.RabbitMq; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; @@ -21,7 +22,8 @@ namespace EShopOnAbp.Shared.Hosting.Microservices; typeof(AbpAspNetCoreMultiTenancyModule), typeof(AbpEventBusRabbitMqModule), typeof(AbpCachingStackExchangeRedisModule), - typeof(AdministrationServiceEntityFrameworkCoreModule) + typeof(AdministrationServiceEntityFrameworkCoreModule), + typeof(AbpDistributedLockingModule) )] public class EShopOnAbpSharedHostingMicroservicesModule : AbpModule { @@ -43,8 +45,7 @@ public class EShopOnAbpSharedHostingMicroservicesModule : AbpModule context.Services .AddDataProtection() .PersistKeysToStackExchangeRedis(redis, "EShopOnAbp-Protection-Keys"); - - + context.Services.AddSingleton(sp => { var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);