refactor: replace GwTenantRoute with GwRoute, change Id type to string
All checks were successful
Publish Platform NuGet Packages / build (push) Successful in 26s

- Remove GwTenantRoute (old tenant-specific route entity)
- Add GwRoute with string Id (Guid.CreateVersion7)
- Update IRouteManager and IRouteStore interfaces
- Update PlatformDbContext configuration for new schema
- GwRoute is now global, tenant-specific routing moved to GwDestination.TenantCode

BREAKING CHANGE: Database schema change requires table recreation
This commit is contained in:
Kimi CLI 2026-03-08 15:21:43 +08:00
parent 61c18916eb
commit b66b231917
6 changed files with 38 additions and 62 deletions

View File

@ -1,17 +1,13 @@
namespace Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
/// <summary>
/// 网关租户路由实体 - 表示路由规则配置
/// 网关路由实体 - 表示全局路由规则配置
/// </summary>
public class GwTenantRoute
public class GwRoute
{
public string Id { get; set; } = Guid.CreateVersion7().ToString("N");
/// <summary>
/// 租户代码
/// </summary>
public string TenantCode { get; set; } = string.Empty;
/// <summary>
/// 服务名称
/// </summary>
@ -67,11 +63,7 @@ public class GwTenantRoute
/// </summary>
public int Status { get; set; } = 1;
/// <summary>
/// 是否全局路由
/// </summary>
public bool IsGlobal { get; set; } = false;
/// <summary>
/// 创建人ID
/// </summary>

View File

@ -9,10 +9,9 @@ namespace Fengling.Platform.Infrastructure;
/// </summary>
public interface IRouteManager
{
Task<GwTenantRoute?> FindByIdAsync(string? id, CancellationToken cancellationToken = default);
Task<GwTenantRoute?> FindByTenantCodeAsync(string tenantCode, CancellationToken cancellationToken = default);
Task<IList<GwTenantRoute>> GetAllAsync(CancellationToken cancellationToken = default);
Task<IdentityResult> CreateRouteAsync(GwTenantRoute route, CancellationToken cancellationToken = default);
Task<IdentityResult> UpdateRouteAsync(GwTenantRoute route, CancellationToken cancellationToken = default);
Task<IdentityResult> DeleteRouteAsync(GwTenantRoute route, CancellationToken cancellationToken = default);
Task<GwRoute?> FindByIdAsync(string? id, CancellationToken cancellationToken = default);
Task<IList<GwRoute>> GetAllAsync(CancellationToken cancellationToken = default);
Task<IdentityResult> CreateRouteAsync(GwRoute route, CancellationToken cancellationToken = default);
Task<IdentityResult> UpdateRouteAsync(GwRoute route, CancellationToken cancellationToken = default);
Task<IdentityResult> DeleteRouteAsync(GwRoute route, CancellationToken cancellationToken = default);
}

View File

@ -9,15 +9,14 @@ namespace Fengling.Platform.Infrastructure;
/// </summary>
public interface IRouteStore
{
Task<GwTenantRoute?> FindByIdAsync(string? id, CancellationToken cancellationToken = default);
Task<GwTenantRoute?> FindByTenantCodeAsync(string tenantCode, CancellationToken cancellationToken = default);
Task<GwTenantRoute?> FindByClusterIdAsync(string clusterId, CancellationToken cancellationToken = default);
Task<IList<GwTenantRoute>> GetAllAsync(CancellationToken cancellationToken = default);
Task<IList<GwTenantRoute>> GetPagedAsync(int page, int pageSize, string? tenantCode = null,
Task<GwRoute?> FindByIdAsync(string? id, CancellationToken cancellationToken = default);
Task<GwRoute?> FindByClusterIdAsync(string clusterId, CancellationToken cancellationToken = default);
Task<IList<GwRoute>> GetAllAsync(CancellationToken cancellationToken = default);
Task<IList<GwRoute>> GetPagedAsync(int page, int pageSize,
string? serviceName = null, RouteStatus? status = null, CancellationToken cancellationToken = default);
Task<int> GetCountAsync(string? tenantCode = null, string? serviceName = null,
Task<int> GetCountAsync(string? serviceName = null,
RouteStatus? status = null, CancellationToken cancellationToken = default);
Task<IdentityResult> CreateAsync(GwTenantRoute route, CancellationToken cancellationToken = default);
Task<IdentityResult> UpdateAsync(GwTenantRoute route, CancellationToken cancellationToken = default);
Task<IdentityResult> DeleteAsync(GwTenantRoute route, CancellationToken cancellationToken = default);
Task<IdentityResult> CreateAsync(GwRoute route, CancellationToken cancellationToken = default);
Task<IdentityResult> UpdateAsync(GwRoute route, CancellationToken cancellationToken = default);
Task<IdentityResult> DeleteAsync(GwRoute route, CancellationToken cancellationToken = default);
}

View File

@ -18,7 +18,7 @@ public class PlatformDbContext(DbContextOptions options)
public DbSet<AuditLog> AuditLogs => Set<AuditLog>();
// Gateway 实体
public DbSet<GwTenantRoute> GwTenantRoutes => Set<GwTenantRoute>();
public DbSet<GwRoute> GwRoutes => Set<GwRoute>();
public DbSet<GwCluster> GwClusters => Set<GwCluster>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
@ -91,10 +91,10 @@ public class PlatformDbContext(DbContextOptions options)
});
// Gateway 实体配置
modelBuilder.Entity<GwTenantRoute>(entity =>
modelBuilder.Entity<GwRoute>(entity =>
{
entity.ToTable("GwRoutes");
entity.HasKey(e => e.Id);
entity.Property(e => e.TenantCode).HasMaxLength(50);
entity.Property(e => e.ServiceName).HasMaxLength(100).IsRequired();
entity.Property(e => e.ClusterId).HasMaxLength(100).IsRequired();
entity.Property(e => e.AuthorizationPolicy).HasMaxLength(100);
@ -132,15 +132,15 @@ public class PlatformDbContext(DbContextOptions options)
c => JsonSerializer.Deserialize<List<GwTransform>>(JsonSerializer.Serialize(c, jsonOptions), jsonOptions)!))
.HasColumnType("jsonb");
entity.HasIndex(e => e.TenantCode);
entity.HasIndex(e => e.ServiceName);
entity.HasIndex(e => e.ClusterId);
entity.HasIndex(e => new { e.ServiceName, e.IsGlobal, e.Status });
entity.HasIndex(e => new { e.ServiceName, e.Status });
});
// GwCluster 聚合根配置
modelBuilder.Entity<GwCluster>(entity =>
{
entity.ToTable("ServiceInstances");
entity.HasKey(e => e.Id);
entity.Property(e => e.ClusterId).HasMaxLength(100).IsRequired();
entity.Property(e => e.Name).HasMaxLength(100).IsRequired();

View File

@ -15,24 +15,21 @@ public class RouteManager : IRouteManager
_store = store;
}
public virtual Task<GwTenantRoute?> FindByIdAsync(string? id, CancellationToken cancellationToken = default)
public virtual Task<GwRoute?> FindByIdAsync(string? id, CancellationToken cancellationToken = default)
=> _store.FindByIdAsync(id, cancellationToken);
public virtual Task<GwTenantRoute?> FindByTenantCodeAsync(string tenantCode, CancellationToken cancellationToken = default)
=> _store.FindByTenantCodeAsync(tenantCode, cancellationToken);
public virtual Task<IList<GwTenantRoute>> GetAllAsync(CancellationToken cancellationToken = default)
public virtual Task<IList<GwRoute>> GetAllAsync(CancellationToken cancellationToken = default)
=> _store.GetAllAsync(cancellationToken);
public virtual Task<IdentityResult> CreateRouteAsync(GwTenantRoute route, CancellationToken cancellationToken = default)
public virtual Task<IdentityResult> CreateRouteAsync(GwRoute route, CancellationToken cancellationToken = default)
{
route.CreatedTime = DateTime.UtcNow;
return _store.CreateAsync(route, cancellationToken);
}
public virtual Task<IdentityResult> UpdateRouteAsync(GwTenantRoute route, CancellationToken cancellationToken = default)
public virtual Task<IdentityResult> UpdateRouteAsync(GwRoute route, CancellationToken cancellationToken = default)
=> _store.UpdateAsync(route, cancellationToken);
public virtual Task<IdentityResult> DeleteRouteAsync(GwTenantRoute route, CancellationToken cancellationToken = default)
public virtual Task<IdentityResult> DeleteRouteAsync(GwRoute route, CancellationToken cancellationToken = default)
=> _store.DeleteAsync(route, cancellationToken);
}

View File

@ -11,45 +11,37 @@ public class RouteStore<TContext> : IRouteStore
where TContext : PlatformDbContext
{
private readonly TContext _context;
private readonly DbSet<GwTenantRoute> _routes;
private readonly DbSet<GwRoute> _routes;
public RouteStore(TContext context)
{
_context = context;
_routes = context.GwTenantRoutes;
_routes = context.GwRoutes;
}
public void Dispose() { }
public virtual Task<GwTenantRoute?> FindByIdAsync(string? id, CancellationToken cancellationToken = default)
public virtual Task<GwRoute?> FindByIdAsync(string? id, CancellationToken cancellationToken = default)
{
if (id == null) return Task.FromResult<GwTenantRoute?>(null);
if (id == null) return Task.FromResult<GwRoute?>(null);
return _routes.FirstOrDefaultAsync(r => r.Id == id, cancellationToken);
}
public virtual Task<GwTenantRoute?> FindByTenantCodeAsync(string tenantCode, CancellationToken cancellationToken = default)
{
return _routes.FirstOrDefaultAsync(r => r.TenantCode == tenantCode && !r.IsDeleted, cancellationToken);
}
public virtual Task<GwTenantRoute?> FindByClusterIdAsync(string clusterId, CancellationToken cancellationToken = default)
public virtual Task<GwRoute?> FindByClusterIdAsync(string clusterId, CancellationToken cancellationToken = default)
{
return _routes.FirstOrDefaultAsync(r => r.ClusterId == clusterId && !r.IsDeleted, cancellationToken);
}
public virtual async Task<IList<GwTenantRoute>> GetAllAsync(CancellationToken cancellationToken = default)
public virtual async Task<IList<GwRoute>> GetAllAsync(CancellationToken cancellationToken = default)
{
return await _routes.Where(r => !r.IsDeleted).ToListAsync(cancellationToken);
}
public virtual async Task<IList<GwTenantRoute>> GetPagedAsync(int page, int pageSize, string? tenantCode = null,
public virtual async Task<IList<GwRoute>> GetPagedAsync(int page, int pageSize,
string? serviceName = null, RouteStatus? status = null, CancellationToken cancellationToken = default)
{
var query = _routes.AsQueryable();
if (!string.IsNullOrEmpty(tenantCode))
query = query.Where(r => r.TenantCode.Contains(tenantCode));
if (!string.IsNullOrEmpty(serviceName))
query = query.Where(r => r.ServiceName.Contains(serviceName));
@ -64,14 +56,11 @@ public class RouteStore<TContext> : IRouteStore
.ToListAsync(cancellationToken);
}
public virtual async Task<int> GetCountAsync(string? tenantCode = null, string? serviceName = null,
public virtual async Task<int> GetCountAsync(string? serviceName = null,
RouteStatus? status = null, CancellationToken cancellationToken = default)
{
var query = _routes.AsQueryable();
if (!string.IsNullOrEmpty(tenantCode))
query = query.Where(r => r.TenantCode.Contains(tenantCode));
if (!string.IsNullOrEmpty(serviceName))
query = query.Where(r => r.ServiceName.Contains(serviceName));
@ -81,14 +70,14 @@ public class RouteStore<TContext> : IRouteStore
return await query.Where(r => !r.IsDeleted).CountAsync(cancellationToken);
}
public virtual async Task<IdentityResult> CreateAsync(GwTenantRoute route, CancellationToken cancellationToken = default)
public virtual async Task<IdentityResult> CreateAsync(GwRoute route, CancellationToken cancellationToken = default)
{
_routes.Add(route);
await _context.SaveChangesAsync(cancellationToken);
return IdentityResult.Success;
}
public virtual async Task<IdentityResult> UpdateAsync(GwTenantRoute route, CancellationToken cancellationToken = default)
public virtual async Task<IdentityResult> UpdateAsync(GwRoute route, CancellationToken cancellationToken = default)
{
route.UpdatedTime = DateTime.UtcNow;
_routes.Update(route);
@ -96,7 +85,7 @@ public class RouteStore<TContext> : IRouteStore
return IdentityResult.Success;
}
public virtual async Task<IdentityResult> DeleteAsync(GwTenantRoute route, CancellationToken cancellationToken = default)
public virtual async Task<IdentityResult> DeleteAsync(GwRoute route, CancellationToken cancellationToken = default)
{
// 软删除
route.IsDeleted = true;