chore 优化代码

This commit is contained in:
2025-10-16 10:30:51 +08:00
parent f1c609b4be
commit 1f5bc3e971
367 changed files with 2705 additions and 3083 deletions

View File

@ -1,9 +1,9 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using System;
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
@ -12,98 +12,99 @@ using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace KonSoft.Shared.Hosting.Microservices.DbMigrations.EfCore
namespace KonSoft.Shared.Hosting.Microservices.DbMigrations.EfCore;
public abstract class PendingEfCoreMigrationsChecker<TDbContext> : ITransientDependency
where TDbContext : DbContext
{
public abstract class PendingEfCoreMigrationsChecker<TDbContext> : ITransientDependency
where TDbContext : DbContext
protected PendingEfCoreMigrationsChecker(
IUnitOfWorkManager unitOfWorkManager,
IServiceProvider serviceProvider,
ICurrentTenant currentTenant,
IDistributedEventBus distributedEventBus,
IAbpDistributedLock abpDistributedLock,
string databaseName)
{
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected IServiceProvider ServiceProvider { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IDistributedEventBus DistributedEventBus { get; }
protected IAbpDistributedLock DistributedLockProvider { get; }
protected string DatabaseName { get; }
UnitOfWorkManager = unitOfWorkManager;
ServiceProvider = serviceProvider;
CurrentTenant = currentTenant;
DistributedEventBus = distributedEventBus;
DistributedLockProvider = abpDistributedLock;
DatabaseName = databaseName;
}
protected PendingEfCoreMigrationsChecker(
IUnitOfWorkManager unitOfWorkManager,
IServiceProvider serviceProvider,
ICurrentTenant currentTenant,
IDistributedEventBus distributedEventBus,
IAbpDistributedLock abpDistributedLock,
string databaseName)
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected IServiceProvider ServiceProvider { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IDistributedEventBus DistributedEventBus { get; }
protected IAbpDistributedLock DistributedLockProvider { get; }
protected string DatabaseName { get; }
public virtual async Task CheckAndApplyDatabaseMigrationsAsync()
{
await TryAsync(LockAndApplyDatabaseMigrationsAsync);
}
protected async Task TryAsync(Func<Task> task, int retryCount = 3)
{
try
{
UnitOfWorkManager = unitOfWorkManager;
ServiceProvider = serviceProvider;
CurrentTenant = currentTenant;
DistributedEventBus = distributedEventBus;
DistributedLockProvider = abpDistributedLock;
DatabaseName = databaseName;
await task();
}
public virtual async Task CheckAndApplyDatabaseMigrationsAsync()
catch (Exception ex)
{
await TryAsync(LockAndApplyDatabaseMigrationsAsync);
}
retryCount--;
protected async Task TryAsync(Func<Task> task, int retryCount = 3)
{
try
if (retryCount <= 0)
{
await task();
throw;
}
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}");
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 Task.Delay(RandomHelper.GetRandom(5000, 15000));
await TryAsync(task, retryCount);
}
}
protected virtual async Task LockAndApplyDatabaseMigrationsAsync()
{
await using (var handle = await DistributedLockProvider.TryAcquireAsync("Migration_" + DatabaseName))
{
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;
}
using (CurrentTenant.Change(null))
{
// Create database tables if needed
using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false))
{
var dbContext = ServiceProvider.GetRequiredService<TDbContext>();
var pendingMigrations = await dbContext
.Database
.GetPendingMigrationsAsync();
if (pendingMigrations.Any())
{
await dbContext.Database.MigrateAsync();
}
await uow.CompleteAsync();
}
await ServiceProvider.GetRequiredService<IDataSeeder>()
.SeedAsync();
}
Log.Information($"Lock is released for db migration and seeding on database named: {DatabaseName}...");
}
await TryAsync(task, retryCount);
}
}
}
protected virtual async Task LockAndApplyDatabaseMigrationsAsync()
{
await using (var handle = await DistributedLockProvider.TryAcquireAsync("Migration_" + DatabaseName))
{
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;
}
using (CurrentTenant.Change(null))
{
// Create database tables if needed
using (var uow = UnitOfWorkManager.Begin(true, false))
{
var dbContext = ServiceProvider.GetRequiredService<TDbContext>();
var pendingMigrations = await dbContext
.Database
.GetPendingMigrationsAsync();
if (pendingMigrations.Any())
{
await dbContext.Database.MigrateAsync();
}
await uow.CompleteAsync();
}
await ServiceProvider.GetRequiredService<IDataSeeder>()
.SeedAsync();
}
Log.Information($"Lock is released for db migration and seeding on database named: {DatabaseName}...");
}
}
}

View File

@ -1,4 +1,6 @@
using KonSoft.Shared.Hosting.AspNetCore;
using System;
using System.Linq;
using KonSoft.Shared.Hosting.AspNetCore;
using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.AspNetCore.Authentication.JwtBearer;
@ -7,8 +9,6 @@ using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;
using System;
using System.Linq;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.BackgroundJobs.RabbitMQ;
@ -21,84 +21,83 @@ using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Swashbuckle;
namespace KonSoft.Shared.Hosting.Microservices
namespace KonSoft.Shared.Hosting.Microservices;
[DependsOn(
typeof(KonSoftSharedHostingAspNetCoreModule),
typeof(AbpBackgroundJobsRabbitMqModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpEventBusRabbitMqModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpDistributedLockingModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpSwashbuckleModule)
)]
public class KonSoftSharedHostingMicroservicesModule : AbpModule
{
[DependsOn(
typeof(KonSoftSharedHostingAspNetCoreModule),
typeof(AbpBackgroundJobsRabbitMqModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpEventBusRabbitMqModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpDistributedLockingModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpSwashbuckleModule)
)]
public class KonSoftSharedHostingMicroservicesModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
ConfigureCache();
ConfigureDataProtection(context, configuration);
ConfigureAuthentication(context, configuration);
ConfigureCors(context, configuration);
}
private void ConfigureCache()
{
Configure<AbpDistributedCacheOptions>(options => { options.KeyPrefix = "KonSoft:"; });
}
private void ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddDataProtection().SetApplicationName("KonSoft")
.PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!),
"KonSoft-Protection-Keys");
context.Services.AddSingleton<IDistributedLockProvider>(_ =>
new RedisDistributedSynchronizationProvider(ConnectionMultiplexer
.Connect(configuration["Redis:Configuration"]!).GetDatabase()));
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = KonSoftConsts.AuthServerAudience;
});
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.WithOrigins(configuration["App:CorsOrigins"]?
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray() ?? [])
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
}
ConfigureCache();
ConfigureDataProtection(context, configuration);
ConfigureAuthentication(context, configuration);
ConfigureCors(context, configuration);
}
}
private void ConfigureCache()
{
Configure<AbpDistributedCacheOptions>(options => { options.KeyPrefix = "KonSoft:"; });
}
private void ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddDataProtection().SetApplicationName("KonSoft")
.PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!),
"KonSoft-Protection-Keys");
context.Services.AddSingleton<IDistributedLockProvider>(_ =>
new RedisDistributedSynchronizationProvider(ConnectionMultiplexer
.Connect(configuration["Redis:Configuration"]!).GetDatabase()));
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = KonSoftConsts.AuthServerAudience;
});
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.WithOrigins(configuration["App:CorsOrigins"]?
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray() ?? [])
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
}
}