From 75b0f9bd353f461f764b8b2418b2eb99aa81bf4a Mon Sep 17 00:00:00 2001 From: movingsam Date: Tue, 3 Mar 2026 15:24:43 +0800 Subject: [PATCH] docs(phase-03): add research and 4 execution plans for gateway restructuring --- .planning/phases/03-/.gitkeep | 0 .planning/phases/03-/03-RESEARCH.md | 325 ++++++++++++++++++ .../03-/03-gateway-cluster-entities-PLAN.md | 207 +++++++++++ .../phases/03-/03-gateway-di-update-PLAN.md | 74 ++++ .../03-gateway-infrastructure-update-PLAN.md | 128 +++++++ .../03-/03-gateway-route-update-PLAN.md | 105 ++++++ 6 files changed, 839 insertions(+) create mode 100644 .planning/phases/03-/.gitkeep create mode 100644 .planning/phases/03-/03-RESEARCH.md create mode 100644 .planning/phases/03-/03-gateway-cluster-entities-PLAN.md create mode 100644 .planning/phases/03-/03-gateway-di-update-PLAN.md create mode 100644 .planning/phases/03-/03-gateway-infrastructure-update-PLAN.md create mode 100644 .planning/phases/03-/03-gateway-route-update-PLAN.md diff --git a/.planning/phases/03-/.gitkeep b/.planning/phases/03-/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.planning/phases/03-/03-RESEARCH.md b/.planning/phases/03-/03-RESEARCH.md new file mode 100644 index 0000000..be46d59 --- /dev/null +++ b/.planning/phases/03-/03-RESEARCH.md @@ -0,0 +1,325 @@ +# Phase 3: 调整网关部分的需求 - 技术研究 + +**日期:** 2026-03-03 +**状态:** 研究完成 + +--- + +## 1. EF Core Owned Entity 配置模式 + +### GwDestination 内嵌实体 + +```csharp +// 在 GwCluster 中配置 Owned Entity +modelBuilder.Entity(entity => +{ + entity.HasKey(e => e.Id); + entity.Property(e => e.ClusterId).HasMaxLength(100).IsRequired(); + entity.HasIndex(e => e.ClusterId).IsUnique(); + + // 配置内嵌的 Destinations 列表 + entity.OwnsMany(e => e.Destinations, dest => + { + dest.WithOwner().HasForeignKey("GwClusterId"); + dest.Property(d => d.DestinationId).HasMaxLength(100).IsRequired(); + dest.Property(d => d.Address).HasMaxLength(200).IsRequired(); + dest.Property(d => d.Health).HasMaxLength(200); + dest.Property(d => d.Weight).HasDefaultValue(1); + dest.Property(d => d.HealthStatus).HasDefaultValue(1); + dest.Property(d => d.Status).HasDefaultValue(1); + + // 复合唯一索引 + dest.HasIndex(d => new { d.DestinationId }).IsUnique(); + }); +}); +``` + +### GwHealthCheckConfig 内嵌值对象 + +```csharp +entity.OwnsOne(e => e.HealthCheck, hc => +{ + hc.Property(h => h.Enabled).HasDefaultValue(false); + hc.Property(h => h.Path).HasMaxLength(100).HasDefaultValue("/health"); + hc.Property(h => h.IntervalSeconds).HasDefaultValue(30); + hc.Property(h => h.TimeoutSeconds).HasDefaultValue(10); +}); +``` + +### GwSessionAffinityConfig 内嵌值对象 + +```csharp +entity.OwnsOne(e => e.SessionAffinity, sa => +{ + sa.Property(s => s.Enabled).HasDefaultValue(false); + sa.Property(s => s.Policy).HasMaxLength(50).HasDefaultValue("Header"); + sa.Property(s => s.AffinityKeyName).HasMaxLength(100).HasDefaultValue("X-Session-Key"); +}); +``` + +--- + +## 2. 实体迁移策略 + +### 删除现有实体 + +```csharp +// 1. 从 PlatformDbContext 中移除 DbSet +public DbSet GwTenants => Set(); // 删除 +public DbSet GwServiceInstances => Set(); // 删除 + +// 2. 移除 OnModelCreating 中的配置 +// modelBuilder.Entity(...) - 删除 +// modelBuilder.Entity(...) - 删除 +``` + +### 创建 EF Core 迁移 + +```bash +# 创建迁移 +dotnet ef migrations add RestructureGatewayEntities --project Fengling.Platform.Infrastructure + +# 迁移将执行: +# - DROP TABLE GwTenants +# - DROP TABLE GwServiceInstances +# - CREATE TABLE GwClusters (包含 Destinations 作为 JSON 或关联表) +# - ALTER TABLE GwTenantRoutes (添加新字段) +``` + +--- + +## 3. GwCluster → YARP ClusterConfig 映射 + +```csharp +public static ClusterConfig ToClusterConfig(this GwCluster cluster) +{ + return new ClusterConfig + { + ClusterId = cluster.ClusterId, + LoadBalancingPolicy = cluster.LoadBalancingPolicy ?? "PowerOfTwoChoices", + Destinations = cluster.Destinations + .Where(d => d.Status == 1) + .ToDictionary( + d => d.DestinationId, + d => new DestinationConfig + { + Address = d.Address, + Health = d.Health, + Metadata = new Dictionary + { + ["Weight"] = d.Weight.ToString() + } + } + ), + HealthCheck = cluster.HealthCheck?.Enabled == true + ? new HealthCheckConfig + { + Active = new ActiveHealthCheckConfig + { + Enabled = true, + Path = cluster.HealthCheck.Path ?? "/health", + Interval = TimeSpan.FromSeconds(cluster.HealthCheck.IntervalSeconds), + Timeout = TimeSpan.FromSeconds(cluster.HealthCheck.TimeoutSeconds) + } + } + : null, + SessionAffinity = cluster.SessionAffinity?.Enabled == true + ? new SessionAffinityConfig + { + Enabled = true, + Policy = cluster.SessionAffinity.Policy, + AffinityKeyName = cluster.SessionAffinity.AffinityKeyName + } + : null + }; +} +``` + +--- + +## 4. GwTenantRoute → YARP RouteConfig 映射 + +```csharp +public static RouteConfig ToRouteConfig(this GwTenantRoute route) +{ + return new RouteConfig + { + RouteId = route.Id, + Match = new RouteMatch + { + Path = route.PathPattern, + Methods = route.Methods?.Split(',').ToList(), + Hosts = route.Hosts?.Split(',').ToList(), + Headers = ParseHeaderMatch(route.Headers) + }, + ClusterId = route.ClusterId, + Order = route.Priority, + Metadata = new Dictionary + { + ["TenantCode"] = route.TenantCode, + ["ServiceName"] = route.ServiceName, + ["IsGlobal"] = route.IsGlobal.ToString() + }, + Transforms = ParseTransforms(route.Transforms) + }; +} + +private static IReadOnlyList? ParseHeaderMatch(string? headersJson) +{ + if (string.IsNullOrEmpty(headersJson)) return null; + + // 解析 JSON 格式的 Header 匹配规则 + // [{"Name":"X-Custom","Values":["value1"],"Mode":"ExactHeader"}] + return JsonSerializer.Deserialize>(headersJson); +} + +private static IReadOnlyList>? ParseTransforms(string? transformsJson) +{ + if (string.IsNullOrEmpty(transformsJson)) return null; + + // 解析 JSON 格式的转换规则 + return JsonSerializer.Deserialize>>(transformsJson); +} +``` + +--- + +## 5. IClusterStore 接口设计 + +```csharp +public interface IClusterStore +{ + // 基础查询 + Task FindByIdAsync(string id, CancellationToken cancellationToken = default); + Task FindByClusterIdAsync(string clusterId, CancellationToken cancellationToken = default); + Task> GetAllAsync(CancellationToken cancellationToken = default); + + // 分页查询 + Task> GetPagedAsync( + int page, + int pageSize, + string? name = null, + ClusterStatus? status = null, + CancellationToken cancellationToken = default); + + Task GetCountAsync( + string? name = null, + ClusterStatus? status = null, + CancellationToken cancellationToken = default); + + // CRUD 操作 + Task CreateAsync(GwCluster cluster, CancellationToken cancellationToken = default); + Task UpdateAsync(GwCluster cluster, CancellationToken cancellationToken = default); + Task DeleteAsync(GwCluster cluster, CancellationToken cancellationToken = default); + + // Destination 管理 + Task AddDestinationAsync(string clusterId, GwDestination destination, CancellationToken cancellationToken = default); + Task UpdateDestinationAsync(string clusterId, GwDestination destination, CancellationToken cancellationToken = default); + Task RemoveDestinationAsync(string clusterId, string destinationId, CancellationToken cancellationToken = default); +} +``` + +--- + +## 6. 会话亲和实现 + +### 中间件:设置会话键 + +```csharp +public class SessionAffinityMiddleware +{ + private readonly RequestDelegate _next; + + public SessionAffinityMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + // 优先使用 UserId + var userId = context.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; + + // 其次使用 TenantCode + var tenantCode = context.User?.FindFirst("TenantCode")?.Value + ?? context.Request.Headers["X-Tenant-Code"].FirstOrDefault(); + + // 设置会话亲和键 + var sessionKey = userId ?? tenantCode ?? "anonymous"; + context.Items["SessionAffinityKey"] = sessionKey; + + // 添加到请求头供 YARP 使用 + context.Request.Headers["X-Session-Key"] = sessionKey; + + await _next(context); + } +} +``` + +--- + +## 7. 依赖关系图 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Wave 1 │ +│ ┌─────────────────┐ ┌─────────────────┐ │ +│ │ GwCluster.cs │ │ GwTenantRoute │ │ +│ │ GwDestination │ │ (扩展字段) │ │ +│ │ 值对象 │ │ │ │ +│ └────────┬────────┘ └────────┬────────┘ │ +│ │ │ │ +└───────────┼────────────────────┼────────────────────────────┘ + │ │ + ▼ ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Wave 2 │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ PlatformDbContext.cs │ │ +│ │ - 移除 GwTenant, GwServiceInstance DbSet │ │ +│ │ - 添加 GwCluster DbSet │ │ +│ │ - 配置 Owned Entities │ │ +│ └─────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Wave 3 │ +│ ┌─────────────────┐ ┌─────────────────┐ │ +│ │ IClusterStore │ │ IRouteStore │ │ +│ │ ClusterStore │ │ RouteStore │ │ +│ │ (替换Instance) │ │ (更新) │ │ +│ └────────┬────────┘ └────────┬────────┘ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ Extensions.cs │ │ +│ │ - 移除 IInstanceStore 注册 │ │ +│ │ - 添加 IClusterStore 注册 │ │ +│ └─────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +--- + +## 8. 风险评估 + +| 风险 | 影响 | 缓解措施 | +|------|------|----------| +| 删除 GwTenant 导致数据丢失 | 高 | 确认无数据后再删除,或提供迁移脚本 | +| 删除 GwServiceInstance 导致数据丢失 | 高 | 同上 | +| EF Core 迁移失败 | 中 | 手动编写 SQL 迁移脚本 | +| Owned Entity 查询性能 | 低 | EF Core 8+ 已优化 | + +--- + +## 9. 参考资源 + +- [EF Core Owned Entities](https://learn.microsoft.com/ef/core/modeling/owned-entities) +- [YARP Configuration](https://microsoft.github.io/reverse-proxy/) +- [YARP GitHub](https://github.com/microsoft/reverse-proxy) +- 项目文档: `docs/yarp-configuration-model.md` + +--- + +*研究完成日期: 2026-03-03* \ No newline at end of file diff --git a/.planning/phases/03-/03-gateway-cluster-entities-PLAN.md b/.planning/phases/03-/03-gateway-cluster-entities-PLAN.md new file mode 100644 index 0000000..0c89898 --- /dev/null +++ b/.planning/phases/03-/03-gateway-cluster-entities-PLAN.md @@ -0,0 +1,207 @@ +--- +phase: 03- +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: + - Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwCluster.cs + - Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwDestination.cs + - Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwHealthCheckConfig.cs + - Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwSessionAffinityConfig.cs +autonomous: true +requirements: + - GATEWAY-RESTRUCTURE-01 + - GATEWAY-RESTRUCTURE-02 +must_haves: + truths: + - "GwCluster 使用 string Id (GUID)" + - "GwDestination 作为 Owned Entity 内嵌" + - "值对象使用 Owned Entity 配置" + artifacts: + - path: "Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwCluster.cs" + provides: "集群聚合根" + min_lines: 50 + - path: "Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwDestination.cs" + provides: "目标端点值对象" + min_lines: 30 + - path: "Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwHealthCheckConfig.cs" + provides: "健康检查配置值对象" + min_lines: 20 + - path: "Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwSessionAffinityConfig.cs" + provides: "会话亲和配置值对象" + min_lines: 20 +--- + +# 计划 01: 创建 GwCluster 聚合根和值对象 + +## 目标 + +创建新的 GwCluster 聚合根及相关值对象,替代原有的 GwServiceInstance 实体设计。 + +**目的:** 将服务实例管理改为集群聚合根模式,内嵌 Destinations 列表,符合 YARP ClusterConfig 结构。 + +**输出:** GwCluster 聚合根、GwDestination 值对象、GwHealthCheckConfig 值对象、GwSessionAffinityConfig 值对象。 + +## 上下文 + +@.planning/phases/03-/03-CONTEXT.md +@.planning/phases/03-/03-RESEARCH.md +@Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwTenantRoute.cs (现有实体参考) +@Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GatewayEnums.cs (枚举) + +## 任务 + + + 任务 1: 创建 GwHealthCheckConfig 值对象 + Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwHealthCheckConfig.cs + +创建健康检查配置值对象: +```csharp +namespace Fengling.Platform.Domain.AggregatesModel.GatewayAggregate; + +/// +/// 健康检查配置(值对象) +/// +public class GwHealthCheckConfig +{ + /// + /// 是否启用健康检查 + /// + public bool Enabled { get; set; } + + /// + /// 健康检查路径 + /// + public string? Path { get; set; } + + /// + /// 检查间隔(秒) + /// + public int IntervalSeconds { get; set; } = 30; + + /// + /// 超时时间(秒) + /// + public int TimeoutSeconds { get; set; } = 10; +} +``` + + 文件可编译 + GwHealthCheckConfig 值对象已创建 + + + + 任务 2: 创建 GwSessionAffinityConfig 值对象 + Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwSessionAffinityConfig.cs + +创建会话亲和配置值对象: +```csharp +namespace Fengling.Platform.Domain.AggregatesModel.GatewayAggregate; + +/// +/// 会话亲和配置(值对象) +/// +public class GwSessionAffinityConfig +{ + /// + /// 是否启用会话亲和 + /// + public bool Enabled { get; set; } + + /// + /// 策略:Header, Cookie + /// + public string Policy { get; set; } = "Header"; + + /// + /// 亲和键名称 + /// + public string AffinityKeyName { get; set; } = "X-Session-Key"; +} +``` + + 文件可编译 + GwSessionAffinityConfig 值对象已创建 + + + + 任务 3: 创建 GwDestination 值对象 + Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwDestination.cs + +创建目标端点值对象: +```csharp +namespace Fengling.Platform.Domain.AggregatesModel.GatewayAggregate; + +/// +/// 目标端点(值对象,内嵌于 GwCluster) +/// +public class GwDestination +{ + /// + /// 目标标识 + /// + public string DestinationId { get; set; } = string.Empty; + + /// + /// 后端地址 + /// + public string Address { get; set; } = string.Empty; + + /// + /// 健康检查端点 + /// + public string? Health { get; set; } + + /// + /// 权重(用于加权负载均衡) + /// + public int Weight { get; set; } = 1; + + /// + /// 健康状态 + /// + public int HealthStatus { get; set; } = 1; + + /// + /// 状态 + /// + public int Status { get; set; } = 1; +} +``` + + 文件可编译 + GwDestination 值对象已创建 + + + + 任务 4: 创建 GwCluster 聚合根 + Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwCluster.cs + +创建 GwCluster 聚合根: +- Id: string (GUID) +- ClusterId: string (业务标识) +- Name: string +- Description: string? +- Destinations: List<GwDestination> (内嵌) +- LoadBalancingPolicy: string +- HealthCheck: GwHealthCheckConfig? +- SessionAffinity: GwSessionAffinityConfig? +- Status: int +- 审计字段 + +参考现有 GwTenantRoute 的结构风格。 + + dotnet build Fengling.Platform.Domain 通过 + GwCluster 聚合根已创建,包含所有字段 + + +## 验证 + +- [ ] 所有 4 个文件已创建 +- [ ] Build 无错误通过 +- [ ] 值对象结构符合 YARP 配置模型 + +## 成功标准 + +Domain 实体准备好进行 Infrastructure 层更新。 \ No newline at end of file diff --git a/.planning/phases/03-/03-gateway-di-update-PLAN.md b/.planning/phases/03-/03-gateway-di-update-PLAN.md new file mode 100644 index 0000000..9c61e32 --- /dev/null +++ b/.planning/phases/03-/03-gateway-di-update-PLAN.md @@ -0,0 +1,74 @@ +--- +phase: 03- +plan: 04 +type: execute +wave: 3 +depends_on: + - 03-gateway-infrastructure-update +files_modified: + - Fengling.Platform.Infrastructure/Extensions.cs + - Fengling.Platform.Infrastructure/GatewayExtensions.cs +autonomous: true +requirements: + - GATEWAY-RESTRUCTURE-07 +must_haves: + truths: + - "Extensions.cs 注册 IClusterStore 而非 IInstanceStore" + - "GatewayExtensions 可独立使用" +--- + +# 计划 04: 更新 Extensions 和 DI 注册 + +## 目标 + +更新 Extensions.cs 以注册新的 IClusterStore,清理旧的 IInstanceStore 注册。 + +**目的:** 完成 DI 容器配置的更新,使新服务可被注入使用。 + +**输出:** 更新的 Extensions.cs。 + +## 上下文 + +@Fengling.Platform.Infrastructure/Extensions.cs +@Fengling.Platform.Infrastructure/GatewayExtensions.cs + +## 任务 + + + 任务 1: 更新 Extensions.cs + Fengling.Platform.Infrastructure/Extensions.cs + +在 AddPlatformCore 方法中: +1. 移除旧注册: + - 移除 services.AddScoped<IInstanceStore, InstanceStore<TContext>>() + - 移除 services.AddScoped<IRouteManager, RouteManager>()(如果之前在 Gateway 部分) + +2. 添加新注册: + - 添加 services.AddScoped<IClusterStore, ClusterStore<TContext>>() + +注意:保持与现有 GatewayExtensions 的兼容性。 + + dotnet build 通过 + Extensions.cs 已更新 + + + + 任务 2: 更新 GatewayExtensions.cs(如需要) + Fengling.Platform.Infrastructure/GatewayExtensions.cs + +检查 GatewayExtensions.cs: +- 如果已注册 IClusterStore,确保与 Extensions.cs 一致 +- 如果需要,添加注释说明两种注册方式 + + dotnet build 通过 + GatewayExtensions 检查完成 + + +## 验证 + +- [ ] Extensions.cs 已更新 +- [ ] Build 无错误通过 + +## 成功标准 + +Gateway 模块重构完成,所有服务正确注册。 \ No newline at end of file diff --git a/.planning/phases/03-/03-gateway-infrastructure-update-PLAN.md b/.planning/phases/03-/03-gateway-infrastructure-update-PLAN.md new file mode 100644 index 0000000..c368d66 --- /dev/null +++ b/.planning/phases/03-/03-gateway-infrastructure-update-PLAN.md @@ -0,0 +1,128 @@ +--- +phase: 03- +plan: 03 +type: execute +wave: 2 +depends_on: + - 03-gateway-cluster-entities + - 03-gateway-route-update +files_modified: + - Fengling.Platform.Infrastructure/PlatformDbContext.cs + - Fengling.Platform.Infrastructure/IInstanceStore.cs + - Fengling.Platform.Infrastructure/InstanceStore.cs + - Fengling.Platform.Infrastructure/IClusterStore.cs + - Fengling.Platform.Infrastructure/ClusterStore.cs +autonomous: true +requirements: + - GATEWAY-RESTRUCTURE-05 + - GATEWAY-RESTRUCTURE-06 +must_haves: + truths: + - "PlatformDbContext 包含GwCluster DbSet" + - "IClusterStore 替代 IInstanceStore" + artifacts: + - path: "Fengling.Platform.Infrastructure/PlatformDbContext.cs" + provides: "更新的 DbContext" + - path: "Fengling.Platform.Infrastructure/IClusterStore.cs" + provides: "集群存储接口" + min_lines: 40 +--- + +# 计划 03: 更新 Infrastructure 层 + +## 目标 + +更新 PlatformDbContext 配置,创建 IClusterStore 接口和实现,替换原有的 IInstanceStore。 + +**目的:** 支持新的 GwCluster 聚合根,移除已废弃的实体 DbSet。 + +**输出:** 更新的 PlatformDbContext、IClusterStore/ClusterStore。 + +## 上下文 + +@Fengling.Platform.Infrastructure/PlatformDbContext.cs +@Fengling.Platform.Infrastructure/IInstanceStore.cs +@Fengling.Platform.Infrastructure/RouteStore.cs (参考模式) + +## 任务 + + + 任务 1: 更新 PlatformDbContext + Fengling.Platform.Infrastructure/PlatformDbContext.cs + +1. 移除 DbSet: + - 移除 DbSet<GwTenant> GwTenants + - 移除 DbSet<GwServiceInstance> GwServiceInstances + +2. 添加 DbSet: + - 添加 DbSet<GwCluster> GwClusters + +3. 在 OnModelCreating 中配置: + - GwCluster 聚合根配置 + - OwnsMany GwDestinations 配置 + - OwnsOne GwHealthCheckConfig 配置 + - OwnsOne GwSessionAffinityConfig 配置 + +参考 03-RESEARCH.md 中的 EF Core 配置代码。 + + dotnet build 通过 + PlatformDbContext 已更新 + + + + 任务 2: 创建 IClusterStore 接口 + Fengling.Platform.Infrastructure/IClusterStore.cs + +创建 IClusterStore 接口,包含: +- FindByIdAsync, FindByClusterIdAsync +- GetAllAsync, GetPagedAsync, GetCountAsync +- CreateAsync, UpdateAsync, DeleteAsync +- AddDestinationAsync, UpdateDestinationAsync, RemoveDestinationAsync + +参考 IRouteStore 模式。 + + 文件可编译 + IClusterStore 接口已创建 + + + + 任务 3: 创建 ClusterStore 实现 + Fengling.Platform.Infrastructure/ClusterStore.cs + +创建 ClusterStore<TContext> 实现 IClusterStore: +- 泛型约束: where TContext : PlatformDbContext +- 实现所有接口方法 +- 支持软删除 +- 支持内嵌 Destination 的 CRUD + +参考 RouteStore 模式。 + + dotnet build 通过 + ClusterStore 实现已创建 + + + + 任务 4: 删除 IInstanceStore 和 InstanceStore + + Fengling.Platform.Infrastructure/IInstanceStore.cs + Fengling.Platform.Infrastructure/InstanceStore.cs + + +删除这两个文件: +- 已被 IClusterStore/ClusterStore 替代 +- 确认无其他引用 + + dotnet build 通过 + 旧文件已删除 + + +## 验证 + +- [ ] PlatformDbContext 已更新 +- [ ] IClusterStore/ClusterStore 已创建 +- [ ] 旧文件已删除 +- [ ] Build 无错误通过 + +## 成功标准 + +Infrastructure 层更新完成,准备更新 DI 注册。 \ No newline at end of file diff --git a/.planning/phases/03-/03-gateway-route-update-PLAN.md b/.planning/phases/03-/03-gateway-route-update-PLAN.md new file mode 100644 index 0000000..68fd3ac --- /dev/null +++ b/.planning/phases/03-/03-gateway-route-update-PLAN.md @@ -0,0 +1,105 @@ +--- +phase: 03- +plan: 02 +type: execute +wave: 1 +depends_on: + - 03-gateway-cluster-entities +files_modified: + - Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwTenantRoute.cs + - Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwTenant.cs + - Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwServiceInstance.cs +autonomous: true +requirements: + - GATEWAY-RESTRUCTURE-03 + - GATEWAY-RESTRUCTURE-04 +must_haves: + truths: + - "GwTenantRoute 扩展了 Methods, Hosts, Headers, Transforms 等字段" + - "旧实体 GwTenant 和 GwServiceInstance 标记为删除或移除" + artifacts: + - path: "Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwTenantRoute.cs" + provides: "扩展的路由实体" + min_lines: 50 +--- + +# 计划 02: 扩展 GwTenantRoute 并删除旧实体 + +## 目标 + +扩展 GwTenantRoute 实体以支持完整的路由匹配能力和转换规则,并删除已废弃的 GwTenant 和 GwServiceInstance 实体。 + +**目的:** 添加 YARP 所需的路由匹配字段,同时清理不再需要的实体。 + +**输出:** 更新的 GwTenantRoute.cs,删除的 GwTenant.cs 和 GwServiceInstance.cs。 + +## 上下文 + +@.planning/phases/03-/03-CONTEXT.md +@Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwTenantRoute.cs (现有) + +## 任务 + + + 任务 1: 扩展 GwTenantRoute 字段 + Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwTenantRoute.cs + +在 GwTenantRoute 中添加以下新字段: + +1. 路由匹配能力: + - Methods?: string (HTTP 方法,如 "GET,POST") + - Hosts?: string (Host 头匹配,如 "api.example.com") + - Headers?: string (Header 匹配规则,JSON 格式) + +2. 策略配置: + - LoadBalancingPolicy?: string (路由级别负载均衡策略覆盖) + - AuthorizationPolicy?: string (授权策略) + - CorsPolicy?: string (CORS 策略) + +3. 请求转换: + - Transforms?: string (请求/响应转换规则,JSON 格式) + +保留现有字段:Id, TenantCode, ServiceName, ClusterId, PathPattern, Priority, Status, IsGlobal + + dotnet build 通过 + GwTenantRoute 已扩展新字段 + + + + 任务 2: 删除 GwTenant 实体 + + Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwTenant.cs + + +删除 GwTenant.cs 文件: +- 原因:使用 Platform.Tenant 通过 TenantCode 关联 +- 确认无其他依赖引用此实体 + + dotnet build 通过 + GwTenant 实体已删除 + + + + 任务 3: 删除 GwServiceInstance 实体 + + Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwServiceInstance.cs + + +删除 GwServiceInstance.cs 文件: +- 原因:改用 GwCluster 聚合根内嵌 Destination +- 确认无其他依赖引用此实体 + + dotnet build 通过 + GwServiceInstance 实体已删除 + + +## 验证 + +- [ ] GwTenantRoute 扩展字段已添加 +- [ ] GwTenant.cs 已删除 +- [ ] GwServiceInstance.cs 已删除 +- [ ] Build 无错误通过 + +## 成功标准 + +Domain 层实体重构完成,准备进行 Infrastructure 层更新。 \ No newline at end of file