From fbc54c9ac55f0f512f412e60f72a9629800465c5 Mon Sep 17 00:00:00 2001 From: Kimi CLI Date: Sun, 8 Mar 2026 15:48:58 +0800 Subject: [PATCH] docs: reorganize documentation, remove GSD workflow files - Add CLEANDDD-WORKFLOW.md - CleanDDD development workflow guide - Keep GATEWAY_ADMIN_README.md and DATABASE_SCHEMA_FIX.md - Remove all .planning/ GSD workflow documents - Remove old EF migrations (using EnsureCreated for test env) --- .planning/PROJECT.md | 100 --- .planning/ROADMAP.md | 93 --- .planning/STATE.md | 83 -- .planning/codebase/ARCHITECTURE.md | 109 --- .planning/codebase/CONCERNS.md | 75 -- .planning/codebase/CONVENTIONS.md | 118 --- .planning/codebase/INTEGRATIONS.md | 86 --- .planning/codebase/STACK.md | 86 --- .planning/codebase/STRUCTURE.md | 96 --- .planning/codebase/TESTING.md | 144 ---- .../docs/gateway-entity-changes-1.0.12.md | 141 ---- .planning/docs/gateway-plugin-system.md | 712 ------------------ .../01-CONTEXT.md | 75 -- .../01-gateway-config-management/01-PLAN.md | 146 ---- .../01-SUMMARY.md | 83 -- .../02-gateway-plugin-system/02-SUMMARY.md | 27 - .../03-gateway-config-broadcast/.gitkeep | 0 .../03-gateway-config-broadcast/03-CONTEXT.md | 74 -- .../03-gateway-config-broadcast/03-PLAN.md | 112 --- .../04-gateway-entity-update/04-PLAN.md | 128 ---- .../04-gateway-entity-update/04-SUMMARY.md | 78 -- GATEWAY_ADMIN_README.md | 87 +++ docs/CLEANDDD-WORKFLOW.md | 183 +++++ 23 files changed, 270 insertions(+), 2566 deletions(-) delete mode 100644 .planning/PROJECT.md delete mode 100644 .planning/ROADMAP.md delete mode 100644 .planning/STATE.md delete mode 100644 .planning/codebase/ARCHITECTURE.md delete mode 100644 .planning/codebase/CONCERNS.md delete mode 100644 .planning/codebase/CONVENTIONS.md delete mode 100644 .planning/codebase/INTEGRATIONS.md delete mode 100644 .planning/codebase/STACK.md delete mode 100644 .planning/codebase/STRUCTURE.md delete mode 100644 .planning/codebase/TESTING.md delete mode 100644 .planning/docs/gateway-entity-changes-1.0.12.md delete mode 100644 .planning/docs/gateway-plugin-system.md delete mode 100644 .planning/phases/01-gateway-config-management/01-CONTEXT.md delete mode 100644 .planning/phases/01-gateway-config-management/01-PLAN.md delete mode 100644 .planning/phases/01-gateway-config-management/01-SUMMARY.md delete mode 100644 .planning/phases/02-gateway-plugin-system/02-SUMMARY.md delete mode 100644 .planning/phases/03-gateway-config-broadcast/.gitkeep delete mode 100644 .planning/phases/03-gateway-config-broadcast/03-CONTEXT.md delete mode 100644 .planning/phases/03-gateway-config-broadcast/03-PLAN.md delete mode 100644 .planning/phases/04-gateway-entity-update/04-PLAN.md delete mode 100644 .planning/phases/04-gateway-entity-update/04-SUMMARY.md create mode 100644 GATEWAY_ADMIN_README.md create mode 100644 docs/CLEANDDD-WORKFLOW.md diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md deleted file mode 100644 index 09eb174..0000000 --- a/.planning/PROJECT.md +++ /dev/null @@ -1,100 +0,0 @@ -# Fengling Console - -## 这是什么 - -Fengling 微服务生态系统的中央管理控制台。负责用户管理、租户管理、OAuth 客户端管理,以及**网关配置管理**。是所有运维操作的中枢后台。 - -## 核心价值 - -统一的管理入口,负责所有运维相关的配置和操作,让其他服务专注于业务逻辑。 - -## 需求 - -### 已验证(现有功能) - -- ✓ 用户管理(CRUD、角色分配)— 已有 -- ✓ 租户管理 — 已有 -- ✓ OAuth 客户端管理 — 已有 -- ✓ 网关服务/路由/实例管理 — 已有(GatewayController) -- ✓ 租户申请审批流程 — 已有 - -### 进行中 - -- [ ] 实现配置变更广播机制(通过 PostgreSQL NOTIFY 通知所有网关实例) -- [ ] 实现 K8s 服务健康检查功能 - -- [ ] 实现配置变更广播机制(通知所有网关实例) -- [ ] 实现 K8s 服务健康检查功能 -- [ ] 集成 Redis pub/sub 用于多实例通信 - -### 范围外 - -- [业务逻辑] — 由各微服务负责 -- [API 认证] — 由 auth-service 负责 -- [服务发现] — 由 service-discovery 负责 - -## 背景 - -**与 Gateway 的关系:** -``` -fengling-console (管理平面) - │ - ├── 用户/租户/配置管理 - │ - └── 网关配置管理 - │ - ├── GatewayDbContext (直接操作数据库) - ├── GatewayController (API) - └── ReloadGatewayAsync() (待实现广播) - │ - ▼ - fengling-gateway (数据平面) - │ - └── 监听配置变更,重新加载 -``` - -**当前问题(来自 CONCERNS.md):** -- OAuth 密钥硬编码 -- CORS 允许所有(开发环境) -- 缺少测试覆盖 -- ReloadGatewayAsync() 为空实现 - -**Console 已有能力:** -- GatewayDbContext - 管理网关路由、集群、实例数据 -- GatewayController - 提供 /api/console/gateway/* API -- GatewayService - 业务逻辑 -- 网关已有 PgSqlConfigChangeListener 使用 NOTIFY/LISTEN,可复用 -- OAuth 密钥硬编码 -- CORS 允许所有(开发环境) -- 缺少测试覆盖 -- Redis 已引用但未使用 -- ReloadGatewayAsync() 为空实现 - -**Console 已有能力:** -- GatewayDbContext - 管理网关路由、集群、实例数据 -- GatewayController - 提供 /api/console/gateway/* API -- GatewayService - 业务逻辑 -- Redis 引用 - 可用于 pub/sub 广播 - -## 约束 - -- **多实例**:Console 必须支持多实例部署 -- **配置广播**:配置变更需要通知所有网关实例 -- **K8s 健康**:Console 需要实现 K8s 服务健康检查 -- **技术栈**:.NET 10.0, ASP.NET Core, PostgreSQL - -## 关键决策 - -| 决策 | 理由 | 结果 | -|------|------|------| -| Console 作为运维中枢 | 集中管理,降低复杂度 | ✓ 良好 | -| Gateway 配置从 Console 变更 | 单一事实来源 | ✓ 良好 | -| PostgreSQL NOTIFY 广播 | 轻量方案,无需额外依赖 | ✓ 良好 | -|------|------|------| -| Console 作为运维中枢 | 集中管理,降低复杂度 | ✓ 良好 | -| Gateway 配置从 Console 变更 | 单一事实来源 | ✓ 良好 | -| Redis pub/sub 广播 | 成熟方案,易于实现 | ✓ 良好 | - ---- - -*最后更新:2026-03-02 初始化后* diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md deleted file mode 100644 index 5669d87..0000000 --- a/.planning/ROADMAP.md +++ /dev/null @@ -1,93 +0,0 @@ -# Roadmap - -## 当前里程碑 - -### Phase 1: 实现 Gateway 配置管理及事件推送 - -- **目标**: 实现 Console 对 Gateway 配置的增删改查功能,并添加事件推送机制,使下游 yarpgateway 能够监听到配置变更 -- **状态**: ✓ 完成 - -#### Goal - -实现 Console 管理 Gateway 配置的完整能力,包括: -- Gateway 配置的 CRUD 操作 -- 配置变更事件推送 -- 下游 Gateway 监听配置变更并重载 - -#### Depends on - -- 无外部依赖 - -#### Plans - -- [x] 01-PLAN.md — 实现配置变更广播机制 - ---- - -### Phase 2: 实现 Gateway 插件系统 - -- **目标**: 实现 YARP 网关的插件系统,包括 Web UI 管理界面和动态编译加载功能 -- **状态**: Not planned yet - -#### Goal - -实现 YARP 网关的插件系统规划与实现,包括: -- Web UI 管理界面(路由管理、集群管理、插件管理) -- 在线 C# 代码编辑(Monaco Editor) -- 动态编译加载(Roslyn) -- 插件生命周期管理 - -#### Depends on - -- Phase 1: 实现 Gateway 配置管理及事件推送 - -#### Plans - -- [ ] 02-PLAN.md — 实施计划 - ---- - -### Phase 3: 网关配置变更广播机制 - -- **目标**: 理解现有网关配置的完整链路:路由 -> 服务 -> 下游服务,梳理配置变更时如何发送新增/变更广播事件 -- **状态**: Planned - -#### Goal - -理解现有网关配置的完整链路: -- 路由配置如何传递到下游服务 -- 服务发现与下游服务的关系 -- 配置变更时的新增/变更广播事件机制 - -#### Depends on - -- Phase 2: 实现 Gateway 插件系统 - -#### Plans - -- [x] 03-PLAN.md — 实施计划 - - ---- - -### Phase 4: 适配 Platform 1.0.12 Gateway 实体变更 - -- **目标**: 适配 Platform 1.0.12 中的 Gateway 实体重构,修复编译错误,更新 Console 代码以使用新的 GwCluster/GwDestination/GwTenantRoute 模型 -WR|- [x] 04-PLAN.md — 实施计划 -NH|- **状态**: Planned - -#### Goal - -适配 Platform 1.0.12 实体变更: -- 移除 IInstanceStore 依赖,改用 IClusterStore -- 更新 GatewayService 使用新的接口方法 -- 更新数据模型映射(GatewayInstanceDto → GwDestination) -- 修复编译错误 - -#### Depends on - -- Phase 3: 网关配置变更广播机制 - -#### Plans - -- [ ] 04-PLAN.md — 实施计划 diff --git a/.planning/STATE.md b/.planning/STATE.md deleted file mode 100644 index 557ac9b..0000000 --- a/.planning/STATE.md +++ /dev/null @@ -1,83 +0,0 @@ -# 状态:Fengling Console - -**最后更新:** 2026-03-04 - ---- - -## 项目引用 - -参考:.planning/PROJECT.md(更新于 2026-03-02) - -**核心价值:** 统一的管理入口,负责所有运维相关的配置和操作,让其他服务专注于业务逻辑。 - -**当前重点:** Phase 4: 待添加(适配 Platform 1.0.12 实体变更) - ---- - -## 项目状态 - -| 项目 | 状态 | -|------|------| -| PROJECT.md | ✓ 已初始化 | -| CODEBASE | ✓ 已有(ARCHITECTURE.md, CONCERNS.md, STACK.md 等) | -| Roadmap | ✓ 已创建 | -| 变更文档 | ✓ 已创建 | - ---- - -## 累积上下文 - -### 初始化 - -- **2026-03-02:** 创建 PROJECT.md,定义 Console 在生态系统中的角色 -- 现有代码库(已有 ARCHITECTURE.md、INTEGRATIONS.md 等) - -### 路线图演进 - -- **2026-03-02:** Phase 1 已添加:实现 Gateway 配置管理及事件推送 -- **2026-03-02:** Phase 1 执行完成 -- **2026-03-02:** Phase 2 已添加:实现 Gateway 插件系统 -- **2026-03-03:** Phase 3 已添加:网关配置变更广播机制 -- **2026-03-03:** Phase 3 已规划 -- **2026-03-03:** Phase 3 上下文已捕获:广播策略 = 仅手动触发 -- **2026-03-04:** Platform 1.0.12 实体变更:Gateway → GwCluster/GwDestination/GwTenantRoute - -### 与 Gateway 的集成 - -| 组件 | 位置 | 现状 | -|------|------|------| -| GatewayDbContext | src/Data/ | 已实现,管理网关配置数据 | -| GatewayController | src/Controllers/ | 已实现,提供 API | -| GatewayService | src/Services/ | 已实现,业务逻辑 | -| ConfigNotificationService | src/Services/ | ✓ 已实现 PostgreSQL NOTIFY | -| ReloadGatewayAsync | src/Services/GatewayService.cs | 待集成通知服务 | - -### 待完成任务 - -- **适配 Platform 1.0.12 实体变更**(编译错误待修复) - ---- - -## 变更记录 - -### Platform 1.0.12 Gateway 实体变更 - -详细变更见:`.planning/docs/gateway-entity-changes-1.0.12.md` - -**主要变更:** -1. GatewayInstance → GwDestination(内嵌值对象) -2. GatewayCluster → GwCluster(聚合根,包含 Destinations) -3. GatewayRoute → GwTenantRoute(通过 ClusterId 关联) -4. IInstanceStore 移除,改用 IClusterStore - ---- - -## 备注 - -- Console 是运维中枢,网关配置的单一管理门户 -- 广播策略:仅手动触发(通过 /reload 接口) -- 下游网关收到通知后自行查询数据库刷新 - ---- - -*最后更新:2026-03-04* diff --git a/.planning/codebase/ARCHITECTURE.md b/.planning/codebase/ARCHITECTURE.md deleted file mode 100644 index 317e15d..0000000 --- a/.planning/codebase/ARCHITECTURE.md +++ /dev/null @@ -1,109 +0,0 @@ -# 架构 - -**分析日期:** 2026-02-28 - -## 模式概述 - -**整体:** 分层架构 + 领域驱动设计 (DDD) - -**关键特性:** -- **控制器层 (Controllers)** - 处理 HTTP 请求,返回 API 响应 -- **服务层 (Services)** - 业务逻辑实现,使用依赖注入 -- **数据访问层** - 通过 Entity Framework Core 访问数据库 -- **领域模型** - 来自外部 Domain 程序集 (Fengling.Platform.Domain) - -## 层次 - -**控制器层 (Controllers):** -- 位置:`src/Controllers/` -- 包含:`UsersController.cs`, `RolesController.cs`, `TenantsController.cs`, `OAuthClientsController.cs`, `GatewayController.cs` -- 职责:处理 HTTP 请求、参数验证、返回响应 -- 依赖:Service 层接口 - -**服务层 (Services):** -- 位置:`src/Services/` -- 包含:`UserService.cs`, `RoleService.cs`, `TenantService.cs`, `OAuthClientService.cs`, `GatewayService.cs`, `H5LinkService.cs` -- 职责:业务逻辑实现、数据转换、事务管理 -- 依赖:Domain 模型、DbContext、UserManager、RoleManager - -**数据层 (Data/Infrastructure):** -- PlatformDbContext - 平台业务数据 -- GatewayDbContext - 网关配置数据 -- 仓储模式:通过 NetCorePal.Extensions.Repository - -**领域层 (Domain - 外部引用):** -- Fengling.Platform.Domain.AggregatesModel.UserAggregate -- Fengling.Platform.Domain.AggregatesModel.RoleAggregate -- Fengling.Platform.Domain.AggregatesModel.TenantAggregate - -## 数据流 - -**典型请求流程:** - -1. **HTTP 请求** → Controller 接收 -2. **参数验证** → DTO 绑定 -3. **业务处理** → Service 层执行 -4. **数据持久化** → EF Core 保存 -5. **响应返回** → Controller 返回结果 - -**状态管理:** -- 无状态 API 设计 -- 状态存储在 PostgreSQL 数据库 -- 认证状态通过 JWT Token 传递 - -## 关键抽象 - -**服务接口:** -- `IUserService` - 用户管理 -- `IRoleService` - 角色管理 -- `ITenantService` - 租户管理 -- `IOAuthClientService` - OAuth 客户端管理 -- `IGatewayService` - 网关配置 -- `IH5LinkService` - H5 链接服务 - -**数据传输对象 (DTO):** -- 位置:`src/Models/Dtos/` -- 模式:CreateXxxDto, UpdateXxxDto, XxxDto, XxxQueryDto -- 用途:API 请求/响应数据结构 - -## 入口点 - -**主入口:** -- 位置:`src/Program.cs` -- 触发:应用启动时执行 -- 职责:服务注册、中间件配置、管道构建 - -**API 端点:** -- `/api/console/[controller]` - RESTful API 前缀 -- `/swagger` - API 文档 - -## 错误处理 - -**策略:** -- 异常捕获 + 日志记录 -- 返回标准 HTTP 状态码 -- 错误详情通过响应体返回 - -**模式:** -```csharp -try { - // 业务逻辑 -} catch (KeyNotFoundException ex) { - return NotFound(); -} catch (InvalidOperationException ex) { - return BadRequest(); -} catch (Exception ex) { - _logger.LogError(ex, "..."); - return StatusCode(500); -} -``` - -## 跨领域关注 - -**日志:** Microsoft.Extensions.Logging + ILogger -**验证:** ASP.NET Core Model Validation + FluentValidation (已引用) -**认证:** OpenIddict + JWT Bearer - ---- - -*架构分析:2026-02-28* diff --git a/.planning/codebase/CONCERNS.md b/.planning/codebase/CONCERNS.md deleted file mode 100644 index c3944fa..0000000 --- a/.planning/codebase/CONCERNS.md +++ /dev/null @@ -1,75 +0,0 @@ -# 代码库问题 - -**分析日期:** 2026-02-28 - -## 技术债务 - -**硬编码密钥:** -- 问题:`src/Program.cs:62` 包含硬编码的 OAuth 客户端密钥 -- 影响:安全风险,不适合生产环境 -- 修复:使用环境变量或密钥管理服务 - -**缺少测试项目:** -- 问题:当前项目没有测试目录 -- 影响:无法进行自动化测试,难以保证代码质量 -- 修复:添加 xUnit/MSTest 测试项目 - -## 已知问题 - -**当前未发现严重 Bug:** -- 代码结构清晰,异常处理完善 - -## 安全考虑 - -**OAuth 密钥硬编码:** -- 风险:生产环境密钥泄露风险 -- 当前缓解:仅在开发环境使用 -- 建议:使用环境变量或密钥 vault - -**CORS 允许所有:** -- 风险:`policy.AllowAnyOrigin()` 存在安全风险 -- 当前缓解:仅开发环境使用 -- 建议:生产环境限制具体域名 - -## 性能问题 - -**当前未发现明显性能瓶颈:** -- 使用 Entity Framework Core 进行数据库查询 -- 支持分页查询,避免大数据量返回 - -## 脆弱区域 - -**审计日志记录:** -- 每次操作都写入审计日志 -- 高并发场景可能成为瓶颈 -- 建议:考虑异步写入或批量处理 - -## 扩展限制 - -**当前架构支持:** -- 水平扩展:通过 Docker 容器化易于扩展 -- 功能扩展:分层架构便于添加新模块 - -## 依赖风险 - -**外部依赖:** -- NetCorePal.Extensions - 自定义扩展库 -- OpenIddict - 社区维护的开源库 -- 建议:关注版本更新,及时升级 - -## 缺失功能 - -**缺失测试覆盖:** -- 无单元测试 -- 无集成测试 -- 无 API 测试 -- 优先级:高 - -**缺失功能:** -- 无缓存层(Redis 已引用但未使用) -- 无消息队列集成 -- 无后台任务系统 - ---- - -*问题审计:2026-02-28* diff --git a/.planning/codebase/CONVENTIONS.md b/.planning/codebase/CONVENTIONS.md deleted file mode 100644 index 07f83e5..0000000 --- a/.planning/codebase/CONVENTIONS.md +++ /dev/null @@ -1,118 +0,0 @@ -# 编码规范 - -**分析日期:** 2026-02-28 - -## 命名模式 - -**文件:** -- PascalCase:`UserService.cs`、`UsersController.cs` - -**类/接口:** -- PascalCase:`UserService`、`IUserService` - -**方法:** -- PascalCase:`GetUsersAsync`、`CreateUserAsync` - -**变量:** -- camelCase:`userService`、`userName` - -## 代码风格 - -**格式化:** -- 使用 .editorconfig 或 Rider/VS 默认格式化 -- 花括号风格:K&R - -**命名空间:** -- 层级式:`Fengling.Console.Controllers` - -## 导入组织 - -**顺序:** -1. System 命名空间 -2. 项目内部命名空间 -3. 第三方库 - -**示例:** -```csharp -using System; -using System.Collections.Generic; -using Fengling.Console.Services; -using Fengling.Platform.Domain; -using Microsoft.AspNetCore.Mvc; -``` - -## 错误处理 - -**模式:** -- 使用 try-catch 捕获异常 -- 按异常类型返回不同 HTTP 状态码 -- 记录日志:`_logger.LogError(ex, "...")` - -**示例:** -```csharp -try { - await _userService.CreateUserAsync(dto); -} catch (InvalidOperationException ex) { - return BadRequest(new { message = ex.Message }); -} catch (Exception ex) { - _logger.LogError(ex, "Error creating user"); - return StatusCode(500, new { message = ex.Message }); -} -``` - -## 日志 - -**框架:** Microsoft.Extensions.Logging + ILogger - -**模式:** -```csharp -private readonly ILogger _logger; - -_logger.LogError(ex, "Error message"); -_logger.LogWarning(ex, "Warning message"); -``` - -## 注释 - -**何时注释:** -- 公开 API 方法使用 XML 文档注释 -- 复杂业务逻辑添加说明 - -**XML 注释示例:** -```csharp -/// -/// 获取用户列表 -/// -/// 分页查询参数 -/// 分页的用户列表 -[HttpGet] -public async Task>> GetUsers(...) -``` - -## 函数设计 - -**大小:** -- 保持方法简洁,单一职责 -- 复杂逻辑拆分到私有方法 - -**参数:** -- 使用 DTO 进行参数分组 -- 异步方法使用 Async 后缀 - -**返回值:** -- 使用 Task 返回异步结果 -- 集合使用 IEnumerable - -## 模块设计 - -**导出:** -- 公开接口:I[Xxx]Service -- 实现类:XxxService - -**依赖注入:** -- 构造函数注入 -- 接口+实现配对 - ---- - -*规范分析:2026-02-28* diff --git a/.planning/codebase/INTEGRATIONS.md b/.planning/codebase/INTEGRATIONS.md deleted file mode 100644 index 6eeda1a..0000000 --- a/.planning/codebase/INTEGRATIONS.md +++ /dev/null @@ -1,86 +0,0 @@ -# 外部集成 - -**分析日期:** 2026-02-28 - -## APIs & 外部服务 - -**身份认证:** -- **OpenIddict** - OAuth 2.0 / OpenID Connect 身份提供商 - - 实现:内置 OpenIddict 认证服务器 - - 客户端:fengling-api - - 密钥:fengling-api-secret(硬编码,见 `src/Program.cs:62`) - - 发行者:http://localhost:5132/ - -**反向代理:** -- **YARP (YarpGateway)** - 反向代理网关 - - 项目引用:`../../fengling-gateway/src/YarpGateway.csproj` - - 用于 API 网关和请求转发 - -## 数据存储 - -**数据库:** -- **PostgreSQL** - 主数据库 - - 连接:`DefaultConnection` (PlatformDbContext) - - 连接:`GatewayConnection` (GatewayDbContext) - - ORM:Entity Framework Core + Npgsql - -**表结构:** -- 用户表 (ApplicationUser) -- 角色表 (ApplicationRole) -- 租户表 (Tenant) -- OAuth 客户端表 -- 审计日志表 (AuditLog) -- 网关配置表 - -## 身份认证 - -**认证方案:** -- OpenIddict Validation (Bearer Token) -- JWT Bearer 认证 -- ASP.NET Core Identity - -**用户管理:** -- ASP.NET Core Identity -- 支持租户隔离 (TenantInfo) - -## 监控与可观测性 - -**日志:** -- 使用 Microsoft.Extensions.Logging -- 通过 ILogger 注入 -- 开发环境启用敏感数据日志 - -**API 文档:** -- Swagger / OpenAPI -- 端点:`/swagger/v1/swagger.json` - -## CI/CD & 部署 - -**主机:** -- Docker 容器化 -- Dockerfile 位于 `src/Dockerfile` - -**CI/CD 流水线:** -- Gitea Actions (`.gitea/workflows/`) - - `deploy.yml` - 部署流水线 - - `docker.yml` - Docker 构建 - - `build.yml` - 构建流水线 - -## 环境配置 - -**必需环境变量:** -- `ConnectionStrings:DefaultConnection` - 平台数据库连接 -- `ConnectionStrings:GatewayConnection` - 网关数据库连接 - -**配置文件:** -- `appsettings.json` - 应用配置 -- `appsettings.Development.json` - 开发配置 - -## Webhooks & 回调 - -**无外部 Webhooks:** -- 当前无外部系统回调集成 - ---- - -*集成审计:2026-02-28* diff --git a/.planning/codebase/STACK.md b/.planning/codebase/STACK.md deleted file mode 100644 index 162cf1d..0000000 --- a/.planning/codebase/STACK.md +++ /dev/null @@ -1,86 +0,0 @@ -# 技术栈 - -**分析日期:** 2026-02-28 - -## 语言 - -**主要:** -- **C#** (.NET 10.0) - 后端 API 开发 - -**次要:** -- **JSON** - 配置文件和数据交换格式 - -## 运行时 - -**环境:** -- .NET 10.0.103 SDK -- ASP.NET Core 10.0 Web 应用 - -**包管理:** -- NuGet -- `global.json` 指定 SDK 版本 10.0.103,rollForward: latestMinor - -## 框架 - -**核心:** -- **ASP.NET Core 10.0** - Web 框架 -- **Entity Framework Core** - ORM,用于数据访问 -- **Npgsql.EntityFrameworkCore.PostgreSQL** - PostgreSQL 数据库驱动 - -**身份认证:** -- **OpenIddict** - OAuth 2.0 / OIDC 身份提供商 -- **Microsoft.AspNetCore.Authentication.JwtBearer** - JWT 令牌认证 - -**其他:** -- **Swashbuckle.AspNetCore** - Swagger/OpenAPI 文档 -- **QRCoder** + **SkiaSharp** - 二维码生成 -- **NetCorePal.Extensions** - 扩展库集合 - -## 关键依赖 - -**核心业务:** -- `Npgsql.EntityFrameworkCore.PostgreSQL` - PostgreSQL 数据库访问 -- `OpenIddict.*` - 身份认证和授权 -- `Microsoft.AspNetCore.Identity.EntityFrameworkCore` - 用户身份管理 - -**扩展库:** -- `NetCorePal.Extensions.AspNetCore` - ASP.NET Core 扩展 -- `NetCorePal.Extensions.DistributedLocks.Redis` - 分布式锁 -- `NetCorePal.Extensions.Repository.EntityFrameworkCore` - 仓储模式 - -**工具库:** -- `Swashbuckle.AspNetCore` - API 文档 -- `QRCoder` + `SkiaSharp` - 二维码生成 -- `Microsoft.OpenApi` - OpenAPI 支持 - -## 项目引用 - -- `YarpGateway` - 反向代理网关 -- `Fengling.Platform.Infrastructure` - 平台基础设施 - -## 配置 - -**环境配置:** -- `appsettings.json` - 默认配置 -- `appsettings.Development.json` - 开发环境配置 -- `launchSettings.json` - 启动配置 - -**数据库连接:** -- `DefaultConnection` - 平台数据库 (PlatformDbContext) -- `GatewayConnection` - 网关数据库 (GatewayDbContext) - -## 平台要求 - -**开发:** -- .NET 10.0 SDK -- PostgreSQL 数据库 -- Visual Studio Code / Rider / Visual Studio - -**生产:** -- Docker 容器化部署 -- Linux 服务器 -- PostgreSQL 数据库 - ---- - -*技术栈分析:2026-02-28* diff --git a/.planning/codebase/STRUCTURE.md b/.planning/codebase/STRUCTURE.md deleted file mode 100644 index 1ba3c90..0000000 --- a/.planning/codebase/STRUCTURE.md +++ /dev/null @@ -1,96 +0,0 @@ -# 代码库结构 - -**分析日期:** 2026-02-28 - -## 目录布局 - -``` -fengling-console/ -├── global.json # .NET SDK 版本配置 -├── Directory.Build.props # 项目共享属性 -├── src/ -│ ├── Fengling.Console.csproj # 主项目文件 -│ ├── Program.cs # 应用入口 -│ ├── Dockerfile # Docker 构建文件 -│ ├── appsettings.json # 应用配置 -│ ├── appsettings.Development.json # 开发环境配置 -│ ├── Properties/ -│ │ └── launchSettings.json # 启动配置 -│ ├── Controllers/ # API 控制器 -│ ├── Services/ # 业务服务层 -│ ├── Models/ -│ │ └── Dtos/ # 数据传输对象 -│ └── bin/Debug/ # 编译输出 -├── .gitea/workflows/ # CI/CD 流水线 -``` - -## 目录用途 - -**src/Controllers/:** -- 用途:API 端点定义 -- 包含文件: - - `UsersController.cs` - 用户管理 API - - `RolesController.cs` - 角色管理 API - - `TenantsController.cs` - 租户管理 API - - `OAuthClientsController.cs` - OAuth 客户端 API - - `GatewayController.cs` - 网关配置 API - - `GlobalUsing.cs` - 全局 using 指令 - -**src/Services/:** -- 用途:业务逻辑实现 -- 包含文件: - - `UserService.cs` - 用户业务逻辑 - - `RoleService.cs` - 角色业务逻辑 - - `TenantService.cs` - 租户业务逻辑 - - `OAuthClientService.cs` - OAuth 客户端逻辑 - - `GatewayService.cs` - 网关配置逻辑 - - `H5LinkService.cs` - H5 链接服务 - -**src/Models/Dtos/:** -- 用途:API 数据传输对象 -- 包含文件: - - CreateXxxDto.cs (CreateUserDto, CreateRoleDto, CreateTenantDto, CreateClientDto) - - UpdateXxxDto.cs (UpdateUserDto, UpdateRoleDto, UpdateTenantDto, UpdateClientDto) - - XxxDto.cs (UserDto, RoleDto, TenantDto, OAuthClientDto, GatewayDto) - - XxxQueryDto.cs (UserQueryDto, RoleQueryDto, TenantQueryDto, OAuthClientQueryDto) - - `PaginationDto.cs` - 分页结果 - - `ResetPasswordDto.cs` - 密码重置 - - `TenantSettingsDto.cs` - 租户设置 - -## 关键文件位置 - -**入口点:** -- `src/Program.cs` - 应用启动配置和服务注册 - -**配置:** -- `src/appsettings.json` - 应用配置 -- `src/appsettings.Development.json` - 开发环境配置 - -**核心逻辑:** -- `src/Services/UserService.cs` - 用户服务实现 -- `src/Controllers/UsersController.cs` - 用户 API - -## 命名约定 - -**文件:** -- PascalCase:`UserService.cs`、`UsersController.cs` - -**目录:** -- PascalCase:`Controllers/`、`Services/`、`Models/Dtos/` - -**类/接口:** -- PascalCase:`UserService`、`IUserService` - -## 新增代码位置 - -**新增功能:** -- API 端点:`src/Controllers/` -- 业务逻辑:`src/Services/` -- DTO:`src/Models/Dtos/` - -**新增测试:** -- 建议位置:单独的测试项目(如 `tests/` 目录) - ---- - -*结构分析:2026-02-28* diff --git a/.planning/codebase/TESTING.md b/.planning/codebase/TESTING.md deleted file mode 100644 index 3cba314..0000000 --- a/.planning/codebase/TESTING.md +++ /dev/null @@ -1,144 +0,0 @@ -# 测试模式 - -**分析日期:** 2026-02-28 - -## 测试框架 - -**未检测到测试框架:** -- 当前项目未包含测试项目 -- 建议添加 xUnit、NUnit 或 MSTest - -**推荐配置:** -- 框架:xUnit -- Mock 库:Moq -- 集成测试:Microsoft.AspNetCore.Mvc.Testing - -## 测试文件组织 - -**建议结构:** -``` -tests/ -├── Fengling.Console.Tests/ -│ ├── Unit/ -│ │ ├── Services/ -│ │ └── Controllers/ -│ └── Integration/ -``` - -## 测试结构 - -**单元测试示例:** -```csharp -public class UserServiceTests -{ - private readonly Mock> _userManagerMock; - private readonly UserService _userService; - - public UserServiceTests() - { - _userManagerMock = new Mock>(...); - _userService = new UserService(...); - } - - [Fact] - public async Task GetUsersAsync_ReturnsPagedResults() - { - // Arrange - var expectedUsers = new List { ... }; - - // Act - var result = await _userService.GetUsersAsync(1, 10); - - // Assert - Assert.Equal(expectedUsers.Count, result.TotalCount); - } -} -``` - -## 模拟 (Mocking) - -**常用 Mock 库:** -- Moq - 主流 Mock 框架 - -**Mock 对象:** -```csharp -var mockUserManager = new Mock>( - store: mockStore.Object, - optionsAccessor: new Mock>().Object, - passwordHasher: new Mock>().Object, - validators: new List>(), - keyNormalizer: new Mock().Object, - errors: new IdentityErrorDescriber(), - logger: new Mock>>().Object, - services: new Mock().Object); -``` - -## Fixture 和工厂 - -**测试数据:** -- 使用静态工厂方法创建测试数据 -- 每个测试方法独立,不共享状态 - -**示例:** -```csharp -public static class TestData -{ - public static CreateUserDto CreateValidUserDto() => new CreateUserDto - { - UserName = "testuser", - Email = "test@example.com", - Password = "Test@123456", - RealName = "Test User" - }; -} -``` - -## 测试类型 - -**单元测试:** -- 范围:Service 层业务逻辑 -- 重点:边界条件、异常处理 - -**集成测试:** -- 范围:Controller API 端点 -- 使用:Microsoft.AspNetCore.Mvc.Testing - -## 常见模式 - -**异步测试:** -```csharp -[Fact] -public async Task CreateUserAsync_ValidInput_ReturnsCreatedUser() -{ - // Arrange - var dto = TestData.CreateValidUserDto(); - - // Act - var result = await _userService.CreateUserAsync(dto); - - // Assert - Assert.NotNull(result); - Assert.Equal(dto.UserName, result.UserName); -} -``` - -**异常测试:** -```csharp -[Fact] -public async Task CreateUserAsync_DuplicateUser_ThrowsException() -{ - // Arrange - var dto = TestData.CreateValidUserDto(); - _userManagerMock - .Setup(x => x.CreateAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(IdentityResult.Failed(new IdentityError { Description = "Duplicate" })); - - // Act & Assert - await Assert.ThrowsAsync(() => - _userService.CreateUserAsync(dto)); -} -``` - ---- - -*测试分析:2026-02-28* diff --git a/.planning/docs/gateway-entity-changes-1.0.12.md b/.planning/docs/gateway-entity-changes-1.0.12.md deleted file mode 100644 index 9ac8287..0000000 --- a/.planning/docs/gateway-entity-changes-1.0.12.md +++ /dev/null @@ -1,141 +0,0 @@ -# Gateway 实体变更记录 - -**变更日期:** 2026-03-04 -**Platform 版本:** 1.0.12 - ---- - -## 变更概述 - -Platform 1.0.12 对 Gateway 相关实体进行了重构,主要变化是将实例(Instance)内嵌到集群(Cluster)中,简化了领域模型。 - ---- - -## 实体变更 - -### 1. GwDestination(新增 - 原 GatewayInstance) - -**旧名称:** GatewayInstance -**新名称:** GwDestination -**类型:** 值对象(内嵌于 GwCluster) - -```csharp -public class GwDestination -{ - public string DestinationId { get; set; } // 目标标识 - public string Address { get; set; } // 后端地址 - public string? Health { get; set; } // 健康检查端点 - public int Weight { get; set; } = 1; // 权重 - public int HealthStatus { get; set; } = 1; // 健康状态 - public int Status { get; set; } = 1; // 状态 -} -``` - -### 2. GwCluster(重构 - 原 GatewayCluster) - -**旧名称:** GatewayCluster -**新名称:** GwCluster -**类型:** 聚合根 - -**主要变化:** -- 包含 `List Destinations` 作为内嵌集合 -- 包含 `GwLoadBalancingPolicy` 负载均衡策略 -- 包含 `GwHealthCheckConfig` 健康检查配置 -- 包含 `GwSessionAffinityConfig` 会话亲和配置 - -### 3. GwTenantRoute(重构 - 原 GatewayRoute) - -**旧名称:** GatewayRoute -**新名称:** GwTenantRoute -**类型:** 实体 - -**主要变化:** -- 通过 `ClusterId` 关联到 `GwCluster` -- 包含 `GwRouteMatch` 路由匹配配置 -- 支持 `GwLoadBalancingPolicy` 路由级别负载均衡覆盖 - ---- - -## 接口变更 - -### IInstanceStore(已移除) - -**状态:** 已移除 - -**原因:** 实例(Destination)现在是 GwCluster 的内嵌对象,不再需要独立的 IInstanceStore 接口。 - -### IClusterStore(新增) - -```csharp -public interface IClusterStore -{ - // Basic CRUD - 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? clusterId = null, - string? name = null, int? status = null, CancellationToken cancellationToken = default); - Task GetCountAsync(string? clusterId = null, string? name = null, - int? status = null, CancellationToken cancellationToken = default); - Task CreateAsync(GwCluster cluster, CancellationToken cancellationToken = default); - Task UpdateAsync(GwCluster cluster, CancellationToken cancellationToken = default); - Task DeleteAsync(GwCluster cluster, CancellationToken cancellationToken = default); - - // Destination management (NEW) - Task AddDestinationAsync(string clusterId, GwDestination destination, CancellationToken cancellationToken = default); - Task UpdateDestinationAsync(string clusterId, string destinationId, GwDestination destination, CancellationToken cancellationToken = default); - Task RemoveDestinationAsync(string clusterId, string destinationId, CancellationToken cancellationToken = default); -} -``` - ---- - -## 架构变化 - -### 旧架构 - -``` -Route → ClusterId → Instance (独立实体) -``` - -### 新架构 - -``` -TenantRoute → ClusterId → GwCluster (聚合根) → List -``` - ---- - -## Console 适配需求 - -由于接口变更,Console 需要进行以下适配: - -1. **移除 IInstanceStore 依赖** - - 移除 `IInstanceStore` 注入 - - 使用 `IClusterStore` 替代 - -2. **更新 GatewayService** - - 实例操作改为通过 `IClusterStore.AddDestinationAsync` 等方法 - - 查询实例改为从 `GwCluster.Destinations` 获取 - -3. **更新数据模型** - - GatewayInstanceDto → 从 GwDestination 映射 - - GatewayClusterDto → 从 GwCluster 映射 - -4. **更新 API 端点** - - `/instances` 相关端点可能需要调整 - ---- - -## 相关文件 - -### Platform 侧 -- `Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwCluster.cs` -- `Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwDestination.cs` -- `Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwTenantRoute.cs` -- `Fengling.Platform.Infrastructure/IClusterStore.cs` -- `Fengling.Platform.Infrastructure/ClusterStore.cs` - -### Console 侧(需要适配) -- `src/Services/GatewayService.cs` - 需要适配新接口 -- `src/Program.cs` - 需要更新依赖注入 diff --git a/.planning/docs/gateway-plugin-system.md b/.planning/docs/gateway-plugin-system.md deleted file mode 100644 index b8b895c..0000000 --- a/.planning/docs/gateway-plugin-system.md +++ /dev/null @@ -1,712 +0,0 @@ -# 网关插件系统技术方案 - -## 一、概述 - -本文档描述 YARP 网关的插件系统规划,包括 Web UI 管理界面和动态编译加载两大核心功能。 - ---- - -## 二、整体架构 - -``` -┌─────────────────────┐ -│ fengling-console │ (运维后端 - Backend) -│ web 前端 │ -└─────────┬───────────┘ - │ HTTP API - ▼ -┌─────────────────────┐ -│ fengling-console │ (运维服务端) -│ │ -│ - 路由管理 API │ ───▶ 数据库持久化 -│ - 集群管理 API │ ───▶ Redis Pub/Sub (发布事件) -│ - 插件管理 API │ -└─────────┬───────────┘ - ▲ - │ 事件订阅 - │ -┌─────────┴───────────┐ -│ fengling-gateway │ (YARP 网关多实例) -│ - YARP 代理 │ -│ - 插件执行 │ -│ - 事件监听 │ -└─────────────────────┘ -``` - -### 项目职责 - -| 项目 | 职责 | -|------|------| -| **fengling-gateway** | 纯 YARP 代理 + 事件订阅 + 插件执行 | -| **fengling-console** | 运维 API + 配置持久化 + 事件发布 | -| **fengling-console-web** | 前端 UI (Monaco Editor) | - ---- - -## 三、Web UI 管理界面 - -### 3.1 技术选型 - -| 项目 | 选择 | 理由 | -|------|------|------| -| 前端框架 | React/Vue | 独立前端项目 | -| 编辑器 | Monaco Editor | VS Code 同款,体验一致 | -| 路由 | `/gateway` | 运维平台内统一路由 | - -### 3.2 功能模块 - -``` -/gateway -├── 路由管理 (Routes) -│ ├── 列表/搜索 -│ ├── 创建/编辑/删除 -│ └── 路由规则配置 -├── 集群管理 (Clusters) -│ ├── 上下游服务列表 -│ ├── 实例管理 -│ └── 健康状态 -├── 插件管理 (Plugins) -│ ├── 已加载插件列表 -│ ├── 上传 DLL -│ └── 在线编写 C# 代码 -└── 监控统计 - ├── QPS/延迟 - └── 流量图表 -``` - -## 一、概述 - -本文档描述 YARP 网关的插件系统规划,包括 Web UI 管理界面和动态编译加载两大核心功能。 - ---- - -## 二、Web UI 管理界面 - -### 2.1 技术选型 - -| 项目 | 选择 | 理由 | -|------|------|------| -| 框架 | Razor Pages | 嵌入主应用,单项目部署 | -| 路由 | `/gateway/ui` | 参考 SwaggerUI 风格 | -| 编辑器 | Monaco Editor | VS Code 同款,体验一致 | - -### 2.2 功能模块 - -``` -/gateway/ui -├── 路由管理 (Routes) -│ ├── 列表/搜索 -│ ├── 创建/编辑/删除 -│ └── 路由规则配置 -├── 集群管理 (Clusters) -│ ├── 上下游服务列表 -│ ├── 实例管理 -│ └── 健康状态 -├── 插件管理 (Plugins) -│ ├── 已加载插件列表 -│ ├── 上传 DLL -│ └── 在线编写 C# 代码 -└── 监控统计 - ├── QPS/延迟 - └── 流量图表 -``` - ---- - -## 三、插件系统架构 - -### 3.1 插件类型定义 - -```csharp -namespace Fengling.Gateway.Plugin.Abstractions -{ - /// - /// 插件基础接口 - /// - public interface IGatewayPlugin - { - string Name { get; } - string Version { get; } - string? Description { get; } - - Task OnLoadAsync(); - Task OnUnloadAsync(); - } - - /// - /// 请求处理插件 - /// - public interface IRequestPlugin : IGatewayPlugin - { - /// 请求到达网关前 - Task OnRequestAsync(HttpContext context); - - /// 路由决策后 - Task OnRouteMatchedAsync(HttpContext context, RouteConfig route); - - /// 转发到后端前 - Task OnForwardingAsync(HttpContext context, HttpRequestMessage request); - } - - /// - /// 响应处理插件 - /// - public interface IResponsePlugin : IGatewayPlugin - { - /// 后端响应后 - Task OnBackendResponseAsync(HttpContext context, HttpResponseMessage response); - - /// 返回客户端前 - Task OnResponseFinalizingAsync(HttpContext context); - } - - /// - /// 路由转换插件 - /// - public interface IRouteTransformPlugin : IGatewayPlugin - { - Task TransformRouteAsync(RouteConfig original, HttpContext context); - } - - /// - /// 负载均衡插件 - /// - public interface ILoadBalancePlugin : IGatewayPlugin - { - Task SelectDestinationAsync( - IReadOnlyList destinations, - HttpContext context); - } -} -``` - -### 3.2 插件阶段枚举 - -```csharp -public enum PipelineStage -{ - None = 0, - OnRequest = 1, // 请求到达网关前 - OnRoute = 2, // 路由决策时 - OnRequestBackend = 3, // 转发到后端前 - OnResponseBackend = 4, // 后端响应后 - OnResponse = 5 // 返回给客户端前 -} -``` - ---- - -## 四、核心模块设计 - -### 4.1 依赖管理(A方案) - -#### 简单场景:直接使用网关已有程序集 - -```csharp -// API 暴露网关程序集 -[ApiController] -public class AssembliesController : ControllerBase -{ - [HttpGet("available")] - public List GetAvailableAssemblies() - { - return AppDomain.CurrentDomain.GetAssemblies() - .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) - .Select(a => new AssemblyInfo - { - Name = a.GetName().Name, - Version = a.GetName().Version?.ToString(), - Location = a.Location - }) - .OrderBy(a => a.Name) - .ToList(); - } -} -``` - -#### 复杂场景:上传 ZIP 包 - -```csharp -public class PluginUploadService -{ - private readonly IObjectStorage _storage; - private readonly PluginDbContext _db; - private readonly string _localPluginPath = "/app/plugins"; - - public async Task UploadPluginAsync(IFormFile zipFile, string pluginName) - { - // 1. 上传到对象存储 - var storageKey = $"plugins/{Guid.NewGuid()}/{zipFile.FileName}"; - await _storage.UploadAsync(zipFile.OpenReadStream(), storageKey); - - // 2. 保存到数据库 - var plugin = new PluginPackage - { - Id = Guid.NewGuid(), - Name = pluginName, - StorageKey = storageKey, - UploadedAt = DateTime.UtcNow, - Status = PluginStatus.Pending - }; - - await _db.PluginPackages.AddAsync(plugin); - await _db.SaveChangesAsync(); - - return plugin; - } - - public async Task ExtractAndLoadAsync(Guid pluginId) - { - var plugin = await _db.PluginPackages.FindAsync(pluginId); - - // 3. 下载到本地 - var localDir = Path.Combine(_localPluginPath, plugin.Id.ToString()); - Directory.CreateDirectory(localDir); - - await _storage.DownloadAsync(plugin.StorageKey, localDir + ".zip"); - - // 4. 解压 - ZipFile.ExtractToDirectory(localDir + ".zip", localDir, overwriteFiles: true); - File.Delete(localDir + ".zip"); - - // 5. 加载插件 - await _pluginManager.LoadFromDirectoryAsync(localDir); - } -} -``` - -#### ZIP 上传验证 - -```csharp -public class PluginValidationService -{ - public async Task ValidateAsync(Stream zipStream) - { - var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - await ExtractZipAsync(zipStream, tempDir); - - try - { - var dlls = Directory.GetFiles(tempDir, "*.dll"); - var result = new PluginValidationResult(); - - foreach (var dll in dlls) - { - var dllResult = await ValidateDllAsync(dll); - result.Assemblies.Add(dllResult); - } - - var validPlugins = result.Assemblies - .Where(a => a.IsValidPlugin) - .ToList(); - - if (validPlugins.Count == 0) - { - result.IsValid = false; - result.ErrorMessage = "未找到实现 IGatewayPlugin 接口的类"; - } - else - { - result.IsValid = true; - result.ValidPluginTypes = validPlugins - .SelectMany(a => a.PluginTypes) - .ToList(); - } - - return result; - } - finally - { - Directory.Delete(tempDir, true); - } - } - - private async Task ValidateDllAsync(string dllPath) - { - var result = new DllValidationResult { DllName = Path.GetFileName(dllPath) }; - - try - { - var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(dllPath); - - var pluginTypes = assembly.GetTypes() - .Where(t => typeof(IGatewayPlugin).IsAssignableFrom(t)) - .Where(t => !t.IsAbstract && !t.IsInterface) - .ToList(); - - if (pluginTypes.Count > 0) - { - result.IsValidPlugin = true; - result.PluginTypes = pluginTypes.Select(t => new PluginTypeInfo - { - TypeName = t.FullName, - ImplementedInterfaces = t.GetInterfaces().Select(i => i.Name).ToList() - }).ToList(); - } - } - catch (Exception ex) - { - result.IsValid = false; - result.ErrorMessage = ex.Message; - } - - return result; - } -} -``` - ---- - -### 4.2 插件间通信(B方案) - -采用**方案 3:强类型 + 弱类型混合** - -#### 插件上下文 - -```csharp -public class GatewayContext -{ - // 预定义常用字段(强类型) - public string? UserId { get; set; } - public string? TenantId { get; set; } - public UserTier Tier { get; set; } - public bool IsAuthenticated { get; set; } - public DateTime RequestTime { get; set; } - - // 扩展数据(弱类型) - public PluginDataBag Data { get; } = new(); -} - -public class PluginDataBag -{ - private readonly Dictionary _data = new(); - - public T? Get(string key) => _data.TryGetValue(key, out var v) ? (T)v : default; - public void Set(string key, T value) => _data[key] = value!; -} -``` - -#### 使用示例 - -```csharp -// 插件 A: 认证 -public class AuthPlugin : IRequestPlugin -{ - public async Task OnRequestAsync(HttpContext context) - { - var userId = ValidateToken(context); - - if (userId != null) - { - context.Items["CurrentUserId"] = userId; - context.Items["IsAuthenticated"] = true; - } - - return context; - } -} - -// 插件 B: 审计 -public class AuditPlugin : IRequestPlugin -{ - public async Task OnRequestAsync(HttpContext context) - { - if (context.Items.TryGetValue("CurrentUserId", out var userId)) - { - await _logger.LogAsync($"User {userId} accessed {context.Request.Path}"); - } - - return context; - } -} -``` - ---- - -### 4.3 在线代码编辑器(C方案) - -采用 **Monaco Editor + 前端模拟补全** - -> **补充说明**:如需更完整的 C# IntelliSense(如真实代码分析、跳转到定义),可使用 Microsoft 官方的 **roslyn-language-server**(VS Code C# 扩展背后使用的语言服务器)。 -> -> **部署方式**: -> ```bash -> # 安装 -> dotnet tool install -g Microsoft.CodeAnalysis.LanguageServer -> -> # 启动服务 -> roslyn-languageserver --port 5000 -> ``` -> -> 前端通过 WebSocket 连接该服务获取完整的语言特性支持。但目前阶段前端模拟补全已足够使用。 - - - -```html - - -
- - -``` - -#### 编辑器模板 - -```csharp -// 生成的代码模板 -$@" -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Fengling.Gateway.Plugin.Abstractions; - -public class {pluginName} : IRequestPlugin -{{ - public string Name => ""{pluginName}""; - public string Version => ""1.0.0""; - - public async Task OnRequestAsync(HttpContext ctx) - {{ - // 编写你的逻辑 - {userCode} - }} -}} -"; -``` - ---- - -### 4.4 插件生命周期管理 - -```csharp -public class PluginManager -{ - private readonly Dictionary _plugins = new(); - private readonly RoslynPluginCompiler _compiler = new(); - - public async Task LoadPluginAsync(byte[] assemblyBytes, string pluginName) - { - // 1. 隔离加载程序集 - var context = new PluginLoadContext(pluginName); - var assembly = context.LoadFromStream(new MemoryStream(assemblyBytes)); - - // 2. 查找插件入口类型 - var pluginType = assembly.GetTypes() - .FirstOrDefault(t => typeof(IGatewayPlugin).IsAssignableFrom(t)); - - if (pluginType == null) - { - context.Unload(); - throw new InvalidOperationException("No IGatewayPlugin implementation found"); - } - - // 3. 创建实例 - var plugin = (IGatewayPlugin)Activator.CreateInstance(pluginType)!; - await plugin.OnLoadAsync(); - - // 4. 保存实例 - var instance = new PluginInstance - { - Name = pluginName, - Assembly = assembly, - Context = context, - Plugin = plugin, - LoadedAt = DateTime.UtcNow - }; - - _plugins[pluginName] = instance; - return instance; - } - - public async Task UnloadPluginAsync(string pluginName) - { - if (!_plugins.TryGetValue(pluginName, out var instance)) - return; - - await instance.Plugin.OnUnloadAsync(); - instance.Context.Unload(); - _plugins.Remove(pluginName); - } -} - -public class PluginLoadContext : AssemblyLoadContext -{ - public PluginLoadContext(string name) : base(name, isCollectible: true) { } - - protected override Assembly? Load(AssemblyName assemblyName) - { - return null; - } -} -``` - ---- - -### 4.5 插件编译服务 - -```csharp -public class RoslynPluginCompiler -{ - private readonly IEnumerable _defaultReferences; - - public RoslynPluginCompiler() - { - _defaultReferences = GetDefaultReferences(); - } - - public CompileResult Compile(string sourceCode, string pluginName, IEnumerable extraAssemblies) - { - var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode); - - var references = _defaultReferences.Concat( - extraAssemblies.Select(a => MetadataReference.CreateFromFile(a)) - ); - - var compilation = CSharpCompilation.Create( - assemblyName: $"Plugin_{pluginName}_{Guid.NewGuid():N}", - syntaxTrees: new[] { syntaxTree }, - references: references, - options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) - .WithAllowUnsafe(false) - .WithOptimizationLevel(OptimizationLevel.Release)); - - using var ms = new MemoryStream(); - var emitResult = compilation.Emit(ms); - - if (!emitResult.Success) - { - return CompileResult.Fail(emitResult.Diagnostics); - } - - ms.Seek(0, SeekOrigin.Begin); - return CompileResult.Success(ms.ToArray()); - } - - private IEnumerable GetDefaultReferences() - { - return AppDomain.CurrentDomain.GetAssemblies() - .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) - .Select(a => MetadataReference.CreateFromFile(a.Location)); - } -} -``` - ---- - -## 五、数据库模型 - -```csharp -public class PluginPackage -{ - public Guid Id { get; set; } - public string Name { get; set; } = string.Empty; - public string Version { get; set; } = "1.0.0"; - public string? Description { get; set; } - public string StorageKey { get; set; } = string.Empty; - public PluginStatus Status { get; set; } - public DateTime UploadedAt { get; set; } - public DateTime? LoadedAt { get; set; } -} - -public class PluginPipeline -{ - public Guid Id { get; set; } - public Guid PluginId { get; set; } - public PipelineStage Stage { get; set; } - public int Order { get; set; } - public bool IsEnabled { get; set; } -} - -public enum PluginStatus -{ - Pending = 0, - Validated = 1, - Loaded = 2, - Failed = 3, - Disabled = 4 -} -``` - ---- - -## 六、实施计划 - -| 阶段 | 任务 | 优先级 | -|------|------|--------| -| Phase 1 | 集成 YARP 到现有项目 | 高 | -| Phase 2 | 插件基础接口定义 | 高 | -| Phase 3 | 插件编译 + 加载框架 | 高 | -| Phase 4 | 嵌入式 Razor UI | 中 | -| Phase 5 | Monaco Editor 集成 | 中 | -| Phase 6 | ZIP 上传验证功能 | 中 | -| Phase 7 | 测试与优化 | 低 | - ---- - -## 七、NuGet 依赖 - -```xml - - - - - - - - -``` - ---- - -## 八、总结 - -本方案实现了: - -1. **Web UI 管理**:类 SwaggerUI 风格的可视化界面 -2. **动态编译**:Roslyn 在线编译 C# 代码 -3. **插件加载**:独立 AssemblyLoadContext,支持热卸载 -4. **灵活扩展**:支持简单场景(使用已有程序集)和复杂场景(上传 ZIP) -5. **流程控制**:插件可分配到 5 个不同阶段执行 - ---- - -*文档版本: 1.0* -*最后更新: 2026-03-01* diff --git a/.planning/phases/01-gateway-config-management/01-CONTEXT.md b/.planning/phases/01-gateway-config-management/01-CONTEXT.md deleted file mode 100644 index 4361f1f..0000000 --- a/.planning/phases/01-gateway-config-management/01-CONTEXT.md +++ /dev/null @@ -1,75 +0,0 @@ -# Phase 1: 实现 Gateway 配置管理及事件推送 - Context - -**收集日期:** 2026-03-02 -**状态:** Ready for planning -**来源:** Manual planning (gsd-tools not available) - -**更新:** 2026-03-03 - 添加数据源决策 - - -## Phase Boundary - -实现 Console 管理 Gateway 配置的完整能力,包括: -- Gateway 配置的 CRUD 操作(已大部实现) -- 配置变更事件推送(待实现) -- 下游 Gateway 监听配置变更并重载 - -**现有能力:** -- GatewayController: API 端点已实现 -- GatewayService: 业务逻辑已实现 -- DTOs: 数据传输对象已定义 - -**待实现:** -- ReloadGatewayAsync() 广播机制 -- 配置变更时自动触发广播 - - - -## Implementation Decisions - -### 技术选型 -- **广播机制**: PostgreSQL NOTIFY/LISTEN(轻量方案,无需额外依赖) -- **备选方案**: Redis pub/sub(如需多实例通信) - -### 数据源 -- **通知服务数据库连接**: 从 EF Core DbContext 获取,而非从配置文件读取 -- **实现方式**: 注入 ConsoleDbContext,使用 `DbContext.Database.GetConnectionString()` - -### 功能决策 -- **自动广播**: 配置变更(创建/更新/删除)时自动触发广播 -- **手动广播**: 提供 /api/console/gateway/reload 手动触发端点 - -### Claude's Discretion -- 具体的 NOTIFY 通道名称格式 -- 事件 payload 结构设计 -- 是否需要事件类型区分(service/route/instance) - - - -## Specific Ideas - -**关键文件:** -- src/Services/GatewayService.cs - ReloadGatewayAsync() 空实现需填充 -- src/Controllers/GatewayController.cs - POST /reload 端点 -- src/Services/ConfigNotificationService.cs - 需修改为使用 DbContext 获取连接字符串 - -**依赖:** -- Npgsql - PostgreSQL 通知(已通过 EF Core 引用) -- Redis(可选)- 如选择 Redis pub/sub - -**参考实现:** -- 网关已有 PgSqlConfigChangeListener 使用 NOTIFY/LISTEN,可复用 - - - -## Deferred Ideas - -- K8s 服务健康检查(后续 Phase) -- Redis pub/sub(如果 PostgreSQL NOTIFY 方案不够用再考虑) - - - ---- - -*Phase: 01-gateway-config-management* -*Context gathered: 2026-03-02, updated 2026-03-03* diff --git a/.planning/phases/01-gateway-config-management/01-PLAN.md b/.planning/phases/01-gateway-config-management/01-PLAN.md deleted file mode 100644 index 1fcaee9..0000000 --- a/.planning/phases/01-gateway-config-management/01-PLAN.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -phase: 01-gateway-config-management -plan: 01 -type: execute -wave: 1 -depends_on: [] -files_modified: - - src/Services/GatewayService.cs - - src/Services/ConfigNotificationService.cs - - src/Data/ConsoleDbContext.cs -autonomous: true -requirements: [] -user_setup: [] - -must_haves: - truths: - - "配置变更后下游 Gateway 能收到通知" - - "手动触发 /reload 端点能广播配置变更" - - "自动触发:服务/路由/实例变更时自动广播" - artifacts: - - path: "src/Services/ConfigNotificationService.cs" - provides: "配置变更通知服务" - contains: "INotificationService" - - path: "src/Services/GatewayService.cs" - provides: "触发通知逻辑" - contains: "ReloadGatewayAsync" - key_links: - - from: "GatewayService" - to: "ConfigNotificationService" - via: "依赖注入" - pattern: "INotificationService" ---- - - -实现配置变更广播机制,使下游 Gateway 能够监听到配置变更。 - - - -@.planning/ROADMAP.md -@.planning/PROJECT.md -@.planning/STATE.md -@.planning/phases/01-gateway-config-management/01-CONTEXT.md -@src/Services/GatewayService.cs -@src/Controllers/GatewayController.cs - - - - - - Task 1: 修改 ConfigNotificationService 使用 DbContext 获取连接字符串 - src/Services/ConfigNotificationService.cs - -修改现有的 PgSqlNotificationService 实现: - -1. 修改构造函数: - - 注入 ConsoleDbContext(而非使用 IConfiguration) - - 使用 DbContext.Database.GetConnectionString() 获取连接字符串 - -2. 移除: - - IConfiguration 依赖 - - _configuration.GetConnectionString("DefaultConnection") - -3. 示例代码: - ```csharp - public PgSqlNotificationService( - ConsoleDbContext dbContext, - ILogger logger) - { - _connectionString = dbContext.Database.GetConnectionString() - ?? throw new InvalidOperationException("DefaultConnection not configured"); - _logger = logger; - } - ``` - -4. 在 Program.cs 中注册服务时传入 DbContext: - ```csharp - services.AddScoped(sp => - new PgSqlNotificationService( - sp.GetRequiredService(), - sp.GetRequiredService>())); - ``` - - - dotnet build --no-restore 2>&1 | head -20 - - PgSqlNotificationService 已修改为使用 DbContext 获取连接字符串 - - - - Task 2: 修改 GatewayService 集成通知服务 - src/Services/GatewayService.cs - -修改 GatewayService 以集成通知服务: - -1. 添加 INotificationService 依赖注入到 GatewayService 构造函数 - -2. 修改 ReloadGatewayAsync() 实现: - - 调用 _notificationService.PublishAsync("gateway_config_changed", JsonSerialize(reloadEvent)) - - 日志记录广播成功 - -3. 在以下 CRUD 操作中添加自动广播(创建/更新/删除后): - - RegisterServiceAsync - 服务注册 - - UnregisterServiceAsync - 服务注销 - - CreateRouteAsync - 路由创建 - - AddInstanceAsync - 实例添加 - - RemoveInstanceAsync - 实例删除 - - UpdateInstanceWeightAsync - 权重更新 - -4. 事件 Payload 格式: - ```json - { - "eventType": "service|route|instance", - "action": "create|update|delete|reload", - "timestamp": "2026-03-02T12:00:00Z", - "details": { ... } - } - ``` - - - dotnet build --no-restore 2>&1 | head -30 - - GatewayService 集成通知服务,所有配置变更操作自动触发广播 - - - - - -整体验证: -1. dotnet build 编译通过 -2. 手动调用 POST /api/console/gateway/reload 返回成功 -3. PostgreSQL 数据库能收到 NOTIFY 消息 - - - -- [x] ConfigNotificationService 改为使用 DbContext 获取连接字符串 -- [ ] INotificationService 接口定义完成 -- [ ] PgSqlNotificationService 实现完成 -- [ ] GatewayService 集成通知服务 -- [ ] ReloadGatewayAsync 触发广播 -- [ ] CRUD 操作自动触发广播 -- [ ] 编译通过 - - - -完成后创建 .planning/phases/01-gateway-config-management/01-SUMMARY.md - diff --git a/.planning/phases/01-gateway-config-management/01-SUMMARY.md b/.planning/phases/01-gateway-config-management/01-SUMMARY.md deleted file mode 100644 index ccf7e1d..0000000 --- a/.planning/phases/01-gateway-config-management/01-SUMMARY.md +++ /dev/null @@ -1,83 +0,0 @@ -# Phase 1: 实现 Gateway 配置管理及事件推送 - 执行摘要 - -**完成日期:** 2026-03-02 -**状态:** ✓ Complete - -## 执行结果 - -| Plan | 任务 | 状态 | -|------|------|------| -| 01 | Task 1: 创建配置通知服务 | ✓ | -| 01 | Task 2: 修改 GatewayService 集成通知服务 | ✓ | - -## 实现的功能 - -### 1. 配置通知服务 (ConfigNotificationService.cs) - -**创建/修改的文件:** -- `src/Services/ConfigNotificationService.cs` - -**包含:** -- `INotificationService` 接口 - 通知服务抽象 -- `PgSqlNotificationService` 实现 - 使用 PostgreSQL NOTIFY 机制 -- `ConfigChangeEvent` - 配置变更事件数据模型 -- 通知通道: `gateway_config_changed` - -**实现细节:** -- 使用 `DbContextOptions` 获取连接字符串(而非直接从配置文件读取) -- 通过反射从 EF Core Npgsql 扩展中提取连接字符串 - -**创建的文件:** -- `src/Services/ConfigNotificationService.cs` - -**包含:** -- `INotificationService` 接口 - 通知服务抽象 -- `PgSqlNotificationService` 实现 - 使用 PostgreSQL NOTIFY 机制 -- `ConfigChangeEvent` - 配置变更事件数据模型 -- 通知通道: `gateway_config_changed` - -**事件格式:** -```json -{ - "eventType": "service|route|instance|gateway", - "action": "create|update|delete|reload", - "timestamp": "2026-03-02T12:00:00Z", - "details": { ... } -} -``` - -### 2. GatewayService 集成 - -**修改的文件:** -- `src/Services/GatewayService.cs` - 添加 INotificationService 依赖 -- `src/Program.cs` - 注册 NotificationService - -**自动广播触发点:** -- `RegisterServiceAsync` - 服务注册时 -- `UnregisterServiceAsync` - 服务注销时 -- `CreateRouteAsync` - 路由创建时 -- `AddInstanceAsync` - 实例添加时 -- `RemoveInstanceAsync` - 实例删除时 -- `UpdateInstanceWeightAsync` - 权重更新时 -- `ReloadGatewayAsync` - 手动触发重载时 - -## 验证 - -- [x] dotnet build 编译通过 -- [x] INotificationService 接口定义完成 -- [x] PgSqlNotificationService 实现完成 -- [x] GatewayService 集成通知服务 -- [x] ReloadGatewayAsync 触发广播 -- [x] CRUD 操作自动触发广播 - -## 下游使用 - -下游 Gateway (yarpgateway) 需要实现: -1. 监听 `gateway_config_changed` 通道 -2. 收到通知后重新加载配置 - ---- - -*Phase: 01-gateway-config-management* -*Plan: 01* -*Executed: 2026-03-02* diff --git a/.planning/phases/02-gateway-plugin-system/02-SUMMARY.md b/.planning/phases/02-gateway-plugin-system/02-SUMMARY.md deleted file mode 100644 index 2474732..0000000 --- a/.planning/phases/02-gateway-plugin-system/02-SUMMARY.md +++ /dev/null @@ -1,27 +0,0 @@ -# Phase 2: 实现 Gateway 插件系统 - -- **目标**: 实现 YARP 网关的插件系统,包括 Web UI 管理界面和动态编译加载功能 -- **状态**: Not planned yet - ---- - -## Goal - -实现 YARP 网关的插件系统规划与实现,包括: - -- Web UI 管理界面(路由管理、集群管理、插件管理) -- 在线 C# 代码编辑(Monaco Editor) -- 动态编译加载(Roslyn) -- 插件生命周期管理 - -## Depends on - -- Phase 1: 实现 Gateway 配置管理及事件推送 - -## Plans - -- [ ] 02-PLAN.md — 实施计划 - ---- - -*相关文档:.planning/docs/gateway-plugin-system.md* diff --git a/.planning/phases/03-gateway-config-broadcast/.gitkeep b/.planning/phases/03-gateway-config-broadcast/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/.planning/phases/03-gateway-config-broadcast/03-CONTEXT.md b/.planning/phases/03-gateway-config-broadcast/03-CONTEXT.md deleted file mode 100644 index f353f6a..0000000 --- a/.planning/phases/03-gateway-config-broadcast/03-CONTEXT.md +++ /dev/null @@ -1,74 +0,0 @@ -# Phase 3: 网关配置变更广播机制 - Context - -**Gathered:** 2026-03-03 -**Status:** Ready for planning - - -## Phase Boundary - -分析现有的网关配置广播机制,梳理路由→服务→下游的完整链路,确定配置变更时的广播策略。 - - - - -## Implementation Decisions - -### 广播触发策略 -- **仅手动触发**:所有 CRUD 操作(路由、集群、实例、权重)不自动广播 -- 下游需要刷新时,手动调用 POST /api/console/gateway/reload -- 事件只通知"需要刷新",不包含具体变更内容 -- 下游收到通知后,自行查询数据库刷新配置 - -### 广播事件格式 -- 通道:`gateway_config_changed` -- 事件内容:只包含 action: "reload",不含具体变更详情 -- 下游逻辑:收到通知 → 查询数据库 → 刷新内存缓存 - -### 需分析的现有代码 -- ConfigNotificationService.cs - 已实现的 NOTIFY 机制 -- GatewayService.cs - 需集成通知服务 -- GatewayController.cs - /reload 接口 - -### Claude's Discretion -- 自动触发 vs 手动触发的具体实现方式 -- 广播失败时的错误处理策略 -- 日志记录细节 - - - - -## Existing Code Insights - -### Reusable Assets -- ConfigNotificationService.cs: PostgreSQL NOTIFY 机制已实现 -- INotificationService 接口: 可直接复用 - -### Established Patterns -- 使用 PgSqlNotificationService 发布通知 -- 通道名称: `gateway_config_changed` - -### Integration Points -- GatewayService 需注入 INotificationService -- ReloadGatewayAsync 需调用通知服务 - - - - -## Specific Ideas - -- 事件 payload 尽量精简,只传递 "reload" action -- 下游网关监听同一数据库连接,收到 NOTIFY 后刷新 - - - - -## Deferred Ideas - -- 自动触发广播(未来可选优化) - - - ---- - -*Phase: 03-gateway-config-broadcast* -*Context gathered: 2026-03-03* diff --git a/.planning/phases/03-gateway-config-broadcast/03-PLAN.md b/.planning/phases/03-gateway-config-broadcast/03-PLAN.md deleted file mode 100644 index a27d826..0000000 --- a/.planning/phases/03-gateway-config-broadcast/03-PLAN.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -phase: 03-gateway-config-broadcast -plan: 01 -type: execute -wave: 1 -depends_on: [] -files_modified: [] -autonomous: true -requirements: [] -user_setup: [] - -must_haves: - truths: - - "现有广播机制已文档化" - - "路由 -> 服务 -> 下游流程已理解" - - "配置变更事件已验证可用" - artifacts: - - path: ".planning/phases/03-gateway-config-broadcast/03-SUMMARY.md" - provides: "阶段执行摘要" - key_links: [] ---- - - -分析和文档化现有的网关配置广播机制。理解从路由配置到下游服务的完整链路,并验证配置变更事件广播是否正常工作。 - - - -@.planning/phases/01-gateway-config-management/01-SUMMARY.md -@.planning/phases/01-gateway-config-management/01-PLAN.md - -## 现有实现(来自 Phase 1) - -广播机制使用 PostgreSQL NOTIFY: -- **通道:** `gateway_config_changed` -- **事件类型:** service, route, instance, gateway -- **操作:** create, update, delete, reload -- **服务:** ConfigNotificationService.cs -- **集成:** GatewayService.cs 在所有 CRUD 操作时触发广播 - - - - - - 任务 1: 分析现有广播实现 - src/Services/ConfigNotificationService.cs, src/Services/GatewayService.cs - -分析现有实现以了解: -1. ConfigNotificationService 如何工作(PostgreSQL NOTIFY) -2. GatewayService 如何在 CRUD 操作时触发广播 -3. 发送的事件类型和载荷是什么 - -阅读源代码并记录发现。 - - - 文件存在且包含通知逻辑 - - 实现分析完成,发现已记录 - - - - 任务 2: 绘制路由 -> 服务 -> 下游流程 - - -文档化完整配置链路: -1. 路由如何在 Console 中定义 -2. 路由如何映射到服务 -3. 下游 Gateway 如何发现服务 -4. 配置变更时,广播如何到达下游 - -参考 src/Models/、src/Services/、src/Controllers/ 中的现有代码 - - - 流程文档已创建 - - 配置链路已文档化 - - - - 任务 3: 验证广播端到端工作 - - -验证广播机制: -1. 检查 PostgreSQL LISTEN/NOTIFY 是否正确配置 -2. 验证 ReloadGatewayAsync 发送正确事件 -3. 确认所有 CRUD 操作(服务/路由/实例)都触发广播 -4. 如可能,测试端到端流程 - - - 编译成功,API 端点可用 - - 广播验证完成 - - - - - -1. 阅读并分析 ConfigNotificationService.cs -2. 阅读并分析 GatewayService.cs -3. 文档化路由 -> 服务 -> 下游流程 -4. 验证编译通过 - - - -- [x] 现有广播实现已分析 -- [x] 配置链路已文档化 -- [x] 广播事件已验证 -- [x] 摘要已创建 - - - -完成后创建 `.planning/phases/03-gateway-config-broadcast/03-SUMMARY.md` - diff --git a/.planning/phases/04-gateway-entity-update/04-PLAN.md b/.planning/phases/04-gateway-entity-update/04-PLAN.md deleted file mode 100644 index ceef3ab..0000000 --- a/.planning/phases/04-gateway-entity-update/04-PLAN.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -phase: 04-gateway-entity-update -plan: 01 -type: execute -wave: 1 -depends_on: [] -files_modified: - - src/Services/GatewayService.cs - - src/Program.cs -autonomous: true -requirements: [] -user_setup: [] - -must_haves: - truths: - - "编译错误已修复" - - "GatewayService 使用新的 IClusterStore 接口" - - "实例操作改为通过 Cluster.Destinations 管理" - artifacts: - - path: "src/Services/GatewayService.cs" - provides: "GatewayService 使用 IClusterStore" - - path: "src/Program.cs" - provides: "依赖注入更新" - key_links: - - from: "GatewayService" - to: "IClusterStore" - via: "依赖注入" ---- - - -适配 Platform 1.0.12 中的 Gateway 实体重构,修复编译错误,更新 Console 代码以使用新的 GwCluster/GwDestination/GwTenantRoute 模型。 - - - -@.planning/docs/gateway-entity-changes-1.0.12.md - -## 编译错误 - -当前编译错误: -``` -error CS0246: IInstanceStore 找不到 -``` - -## 变更摘要 - -1. **IInstanceStore 已移除** - 实例现在是 GwCluster 的内嵌对象 -2. **IClusterStore 是新接口** - 包含 Destination 管理方法 -3. **数据模型变化**: - - GatewayInstance → GwDestination(内嵌值对象) - - GatewayCluster → GwCluster(聚合根,包含 Destinations) - - 路由通过 ClusterId 关联到集群 - - - - - - - 任务 1: 更新 Program.cs 依赖注入 - src/Program.cs - -1. 移除 IInstanceStore 的注入(如果有) -2. 添加 IClusterStore 的注入: - ```csharp - builder.Services.AddScoped>(); - ``` -3. 确保使用正确的 PlatformDbContext - - - dotnet build --no-restore 2>&1 | head -30 - - Program.cs 依赖注入已更新 - - - - 任务 2: 更新 GatewayService 使用 IClusterStore - src/Services/GatewayService.cs - -1. 移除 IInstanceStore 依赖 -2. 添加 IClusterStore 依赖注入 -3. 更新实例相关方法: - - GetInstancesAsync → 从 Cluster.Destinations 获取 - - AddInstanceAsync → 使用 IClusterStore.AddDestinationAsync - - RemoveInstanceAsync → 使用 IClusterStore.RemoveDestinationAsync - - UpdateInstanceWeightAsync → 使用 IClusterStore.UpdateDestinationAsync -4. 更新数据模型映射: - - GatewayInstanceDto → 从 GwDestination 映射 - - GatewayClusterDto → 从 GwCluster 映射 - - - dotnet build --no-restore 2>&1 | head -30 - - GatewayService 已更新为使用 IClusterStore - - - - 任务 3: 验证编译通过 - - -运行完整编译验证: -```bash -dotnet build src/Fengling.Console.csproj -``` -确保没有编译错误。 - - - dotnet build src/Fengling.Console.csproj 2>&1 | tail -10 - - 编译通过,无错误 - - - - - -1. dotnet build 编译通过 -2. GatewayService 使用 IClusterStore -3. 实例操作通过 Cluster.Destinations 管理 - - - -- [x] IInstanceStore 依赖已移除 -- [x] IClusterStore 已集成 -- [x] 编译错误已修复 -- [x] GatewayService 功能正常 - - - -完成后创建 `.planning/phases/04-gateway-entity-update/04-SUMMARY.md` - diff --git a/.planning/phases/04-gateway-entity-update/04-SUMMARY.md b/.planning/phases/04-gateway-entity-update/04-SUMMARY.md deleted file mode 100644 index 27205bc..0000000 --- a/.planning/phases/04-gateway-entity-update/04-SUMMARY.md +++ /dev/null @@ -1,78 +0,0 @@ -# Phase 4 总结:适配 Platform 1.0.12 Gateway 实体变更 - -## 概述 - -本次 Phase 4 成功完成了 Fengling Console 对 Platform 1.0.12 Gateway 实体变更的适配工作。 - -## 主要变更 - -### 1. Program.cs 依赖注入更新 - -**变更内容:** -- 移除了 `IInstanceStore` 和 `InstanceStore` 的注册 -- 保留了 `IClusterStore` 和 `ClusterStore` 的注册 - -**变更原因:** -Platform 1.0.12 移除了 `IInstanceStore` 接口,实例(Destination)现在是 `GwCluster` 的内嵌对象。 - -### 2. ConsoleDbContext 实体配置清理 - -**变更内容:** -- 移除了 `GwTenant` 实体配置(原平台中已移除) -- 移除了 `GwServiceInstance` 实体配置(已重构为 GwDestination) - -### 3. GatewayService 实体属性适配 - -**变更内容:** - -| 旧属性 | 新属性 | 说明 | -|--------|--------|------| -| `GwTenantRoute.PathPattern` (string) | `GwTenantRoute.Match.Path` ( GwRouteMatch.Path ) | 路由匹配配置从简单字符串升级为复杂对象 | -| `Status = RouteStatus.Active` (enum) | `Status = (int)RouteStatus.Active` (int) | Status 字段为 int 类型,需要显式转换枚举 | - -**具体代码变更:** - -```csharp -// 旧代码 -new GwTenantRoute -{ - PathPattern = pathPattern, - Status = RouteStatus.Active, -} - -// 新代码 -new GwTenantRoute -{ - Match = new GwRouteMatch { Path = pathPattern }, - Status = (int)RouteStatus.Active, -} -``` - -```csharp -// 旧代码读取 -r.PathPattern -r.Status - -// 新代码读取 -r.Match.Path -r.Status (已是 int) -``` - -## 编译结果 - -✅ 编译成功,0 个错误,3 个警告(警告为预存在的代码质量问题,与本次变更无关) - -## 验证 - -- [x] `dotnet build` 通过 -- [x] 无新增编译错误 - -## 相关文档 - -- 实体变更详情:`.planning/docs/gateway-entity-changes-1.0.12.md` - -## 下一步 - -可以考虑的改进: -1. 修复 TenantService.cs 中的警告(roleManager 参数未使用) -2. 完善 GatewayService 中的空值处理(Match 可能为 null) diff --git a/GATEWAY_ADMIN_README.md b/GATEWAY_ADMIN_README.md new file mode 100644 index 0000000..c19fda6 --- /dev/null +++ b/GATEWAY_ADMIN_README.md @@ -0,0 +1,87 @@ +# Gateway Admin - 独立前端项目 + +## 项目结构 + +``` +fengling-console/ +├── src/ +│ ├── Controllers/ +│ │ └── GatewayAdminController.cs # Gateway Admin API +│ ├── wwwroot/ +│ │ └── gateway-admin/ # Vue3 构建输出 (gitignore) +│ └── ... +├── gateway-admin-client/ # Vue3 + shadcn-vue 独立项目 +│ ├── src/ +│ │ ├── components/ # UI 组件 +│ │ ├── views/ # 页面 +│ │ │ ├── Dashboard.vue # 仪表盘 +│ │ │ ├── Routes.vue # 路由管理 +│ │ │ ├── Clusters.vue # 集群管理 +│ │ │ └── Discovery.vue # 服务发现 +│ │ ├── api/ +│ │ │ └── gateway.ts # API 客户端 +│ │ ├── App.vue # 根组件 +│ │ └── main.ts # 入口 +│ ├── package.json +│ ├── vite.config.ts # 构建输出到 ../src/wwwroot/gateway-admin/ +│ └── ... +└── ... +``` + +## 与 Vben Admin 的关系 + +- **Vben Admin** (`fengling-console-web/`): 管理非网关部分(用户、角色、租户等) +- **Gateway Admin** (`gateway-admin-client/`): 独立的网关管理界面 + +**集成方式**: Vben Admin 通过 `