From 9516e1cd93f94c9f342d1d7a6118af99b9856bd9 Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 15 Feb 2026 10:34:07 +0800 Subject: [PATCH] refactor: major project restructuring and cleanup Changes: - Remove deprecated Fengling.Activity and YarpGateway.Admin projects - Add points processing services with distributed lock support - Update Vben frontend with gateway management pages - Add gateway config controller and database listener - Update routing to use header-mixed-nav layout - Add comprehensive test suites for Member services - Add YarpGateway integration tests - Update package versions in Directory.Packages.props Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- Program.cs | 2 + Services/GatewayService.cs | 80 ++++++++++++++------------------------ 2 files changed, 31 insertions(+), 51 deletions(-) diff --git a/Program.cs b/Program.cs index 2080052..21e63ae 100644 --- a/Program.cs +++ b/Program.cs @@ -39,6 +39,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddOpenIddict() .AddCore(options => @@ -79,6 +80,7 @@ builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new() { Title = "Fengling.Console API", Version = "v1" }); + c.CustomSchemaIds(type => type.FullName); // Use full name to avoid conflicts with YarpGateway DTOs var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); if (File.Exists(xmlPath)) diff --git a/Services/GatewayService.cs b/Services/GatewayService.cs index acf71c9..133473e 100644 --- a/Services/GatewayService.cs +++ b/Services/GatewayService.cs @@ -24,21 +24,19 @@ public interface IGatewayService public class GatewayService : IGatewayService { - private readonly IDbContextFactory _dbContextFactory; + private readonly GatewayDbContext _dbContext; private readonly ILogger _logger; - public GatewayService(IDbContextFactory dbContextFactory, ILogger logger) + public GatewayService(GatewayDbContext dbContext, ILogger logger) { - _dbContextFactory = dbContextFactory; + _dbContext = dbContext; _logger = logger; } public async Task GetStatisticsAsync() { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var routes = await db.TenantRoutes.Where(r => !r.IsDeleted).ToListAsync(); - var instances = await db.ServiceInstances.Where(i => !i.IsDeleted).ToListAsync(); + var routes = await _dbContext.TenantRoutes.Where(r => !r.IsDeleted).ToListAsync(); + var instances = await _dbContext.ServiceInstances.Where(i => !i.IsDeleted).ToListAsync(); return new GatewayStatisticsDto { @@ -57,9 +55,7 @@ public class GatewayService : IGatewayService public async Task> GetServicesAsync(bool globalOnly = false, string? tenantCode = null) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var query = db.TenantRoutes.Where(r => !r.IsDeleted); + var query = _dbContext.TenantRoutes.Where(r => !r.IsDeleted); if (globalOnly) query = query.Where(r => r.IsGlobal); @@ -69,7 +65,7 @@ public class GatewayService : IGatewayService var routes = await query.OrderByDescending(r => r.CreatedTime).ToListAsync(); var clusters = routes.Select(r => r.ClusterId).Distinct().ToList(); - var instances = await db.ServiceInstances + var instances = await _dbContext.ServiceInstances .Where(i => clusters.Contains(i.ClusterId) && !i.IsDeleted) .GroupBy(i => i.ClusterId) .ToDictionaryAsync(g => g.Key, g => g.Count()); @@ -79,9 +75,7 @@ public class GatewayService : IGatewayService public async Task GetServiceAsync(string serviceName, string? tenantCode = null) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var route = await db.TenantRoutes + var route = await _dbContext.TenantRoutes .FirstOrDefaultAsync(r => r.ServiceName == serviceName && r.IsDeleted == false && @@ -89,7 +83,7 @@ public class GatewayService : IGatewayService if (route == null) return null; - var instances = await db.ServiceInstances + var instances = await _dbContext.ServiceInstances .CountAsync(i => i.ClusterId == route.ClusterId && !i.IsDeleted); return MapToServiceDto(route, instances); @@ -97,8 +91,6 @@ public class GatewayService : IGatewayService public async Task RegisterServiceAsync(CreateGatewayServiceDto dto) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - var clusterId = $"{dto.ServicePrefix}-service"; var pathPattern = $"/{dto.ServicePrefix}/{dto.Version}/{{**path}}"; var destinationId = string.IsNullOrEmpty(dto.DestinationId) @@ -106,7 +98,7 @@ public class GatewayService : IGatewayService : dto.DestinationId; // Check if route already exists - var existingRoute = await db.TenantRoutes + var existingRoute = await _dbContext.TenantRoutes .FirstOrDefaultAsync(r => r.ServiceName == dto.ServicePrefix && r.IsGlobal == dto.IsGlobal && @@ -130,7 +122,7 @@ public class GatewayService : IGatewayService Status = 1, CreatedTime = DateTime.UtcNow }; - await db.ServiceInstances.AddAsync(instance); + await _dbContext.ServiceInstances.AddAsync(instance); // Add route var routeId = instanceId + 1; @@ -146,9 +138,9 @@ public class GatewayService : IGatewayService IsGlobal = dto.IsGlobal, CreatedTime = DateTime.UtcNow }; - await db.TenantRoutes.AddAsync(route); + await _dbContext.TenantRoutes.AddAsync(route); - await db.SaveChangesAsync(); + await _dbContext.SaveChangesAsync(); _logger.LogInformation("Registered service {Service} at {Address}", dto.ServicePrefix, dto.ServiceAddress); @@ -157,9 +149,7 @@ public class GatewayService : IGatewayService public async Task UnregisterServiceAsync(string serviceName, string? tenantCode = null) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var route = await db.TenantRoutes + var route = await _dbContext.TenantRoutes .FirstOrDefaultAsync(r => r.ServiceName == serviceName && r.IsDeleted == false && @@ -172,7 +162,7 @@ public class GatewayService : IGatewayService route.UpdatedTime = DateTime.UtcNow; // Soft delete instances - var instances = await db.ServiceInstances + var instances = await _dbContext.ServiceInstances .Where(i => i.ClusterId == route.ClusterId && !i.IsDeleted) .ToListAsync(); @@ -182,7 +172,7 @@ public class GatewayService : IGatewayService instance.UpdatedTime = DateTime.UtcNow; } - await db.SaveChangesAsync(); + await _dbContext.SaveChangesAsync(); _logger.LogInformation("Unregistered service {Service}", serviceName); @@ -191,9 +181,7 @@ public class GatewayService : IGatewayService public async Task> GetRoutesAsync(bool globalOnly = false) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var query = db.TenantRoutes.Where(r => !r.IsDeleted); + var query = _dbContext.TenantRoutes.Where(r => !r.IsDeleted); if (globalOnly) query = query.Where(r => r.IsGlobal); @@ -201,7 +189,7 @@ public class GatewayService : IGatewayService var routes = await query.OrderByDescending(r => r.Priority).ToListAsync(); var clusters = routes.Select(r => r.ClusterId).Distinct().ToList(); - var instances = await db.ServiceInstances + var instances = await _dbContext.ServiceInstances .Where(i => clusters.Contains(i.ClusterId) && !i.IsDeleted) .GroupBy(i => i.ClusterId) .ToDictionaryAsync(g => g.Key, g => g.Count()); @@ -222,9 +210,7 @@ public class GatewayService : IGatewayService public async Task CreateRouteAsync(CreateGatewayRouteDto dto) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var existing = await db.TenantRoutes + var existing = await _dbContext.TenantRoutes .FirstOrDefaultAsync(r => r.ServiceName == dto.ServiceName && r.IsGlobal == dto.IsGlobal && @@ -248,8 +234,8 @@ public class GatewayService : IGatewayService CreatedTime = DateTime.UtcNow }; - await db.TenantRoutes.AddAsync(route); - await db.SaveChangesAsync(); + await _dbContext.TenantRoutes.AddAsync(route); + await _dbContext.SaveChangesAsync(); return new GatewayRouteDto { @@ -267,9 +253,7 @@ public class GatewayService : IGatewayService public async Task> GetInstancesAsync(string clusterId) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var instances = await db.ServiceInstances + var instances = await _dbContext.ServiceInstances .Where(i => i.ClusterId == clusterId && !i.IsDeleted) .OrderByDescending(i => i.Weight) .ToListAsync(); @@ -289,9 +273,7 @@ public class GatewayService : IGatewayService public async Task AddInstanceAsync(CreateGatewayInstanceDto dto) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var existing = await db.ServiceInstances + var existing = await _dbContext.ServiceInstances .FirstOrDefaultAsync(i => i.ClusterId == dto.ClusterId && i.DestinationId == dto.DestinationId && @@ -314,8 +296,8 @@ public class GatewayService : IGatewayService CreatedTime = DateTime.UtcNow }; - await db.ServiceInstances.AddAsync(instance); - await db.SaveChangesAsync(); + await _dbContext.ServiceInstances.AddAsync(instance); + await _dbContext.SaveChangesAsync(); return new GatewayInstanceDto { @@ -332,29 +314,25 @@ public class GatewayService : IGatewayService public async Task RemoveInstanceAsync(long instanceId) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var instance = await db.ServiceInstances.FindAsync(instanceId); + var instance = await _dbContext.ServiceInstances.FindAsync(instanceId); if (instance == null) return false; instance.IsDeleted = true; instance.UpdatedTime = DateTime.UtcNow; - await db.SaveChangesAsync(); + await _dbContext.SaveChangesAsync(); return true; } public async Task UpdateInstanceWeightAsync(long instanceId, int weight) { - await using var db = await _dbContextFactory.CreateDbContextAsync(); - - var instance = await db.ServiceInstances.FindAsync(instanceId); + var instance = await _dbContext.ServiceInstances.FindAsync(instanceId); if (instance == null) return false; instance.Weight = weight; instance.UpdatedTime = DateTime.UtcNow; - await db.SaveChangesAsync(); + await _dbContext.SaveChangesAsync(); return true; }