diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index ea81567..e5c8084 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -47,22 +47,22 @@
---
-BY|RR|### Phase 3: 网关配置变更广播机制
-PZ|
-RS|- **目标**: 理解现有网关配置的完整链路:路由 -> 服务 -> 下游服务,梳理配置变更时如何发送新增/变更广播事件
-NH|- **状态**: Planned
-YJ|
-HK|#### Goal
-XN|
-MZ|理解现有网关配置的完整链路:
-SS|- 路由配置如何传递到下游服务
-VZ|- 服务发现与下游服务的关系
-XB|- 配置变更时的新增/变更广播事件机制
-VW|
-KJ|#### Depends on
-JN|
-XS|- Phase 2: 实现 Gateway 插件系统
-PZ|
-WR|#### Plans
-TH|
-BY|- [x] 03-PLAN.md — 实施计划
+### Phase 3: 网关配置变更广播机制
+
+- **目标**: 理解现有网关配置的完整链路:路由 -> 服务 -> 下游服务,梳理配置变更时如何发送新增/变更广播事件
+- **状态**: Planned
+
+#### Goal
+
+理解现有网关配置的完整链路:
+- 路由配置如何传递到下游服务
+- 服务发现与下游服务的关系
+- 配置变更时的新增/变更广播事件机制
+
+#### Depends on
+
+- Phase 2: 实现 Gateway 插件系统
+
+#### Plans
+
+- [x] 03-PLAN.md — 实施计划
diff --git a/.planning/STATE.md b/.planning/STATE.md
index bc084a6..0c535ac 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -1,6 +1,6 @@
# 状态:Fengling Console
-**最后更新:** 2026-03-02
+**最后更新:** 2026-03-03
---
@@ -10,7 +10,7 @@
**核心价值:** 统一的管理入口,负责所有运维相关的配置和操作,让其他服务专注于业务逻辑。
-**当前重点:** 待规划
+**当前重点:** Phase 3: 上下文已捕获
---
@@ -20,7 +20,7 @@
|------|------|
| PROJECT.md | ✓ 已初始化 |
| CODEBASE | ✓ 已有(ARCHITECTURE.md, CONCERNS.md, STACK.md 等) |
-| Roadmap | 未创建 |
+| Roadmap | ✓ 已创建 |
---
@@ -31,6 +31,15 @@
- **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 上下文已捕获:广播策略 = 仅手动触发
+
### 与 Gateway 的集成
| 组件 | 位置 | 现状 |
@@ -38,21 +47,21 @@
| GatewayDbContext | src/Data/ | 已实现,管理网关配置数据 |
| GatewayController | src/Controllers/ | 已实现,提供 API |
| GatewayService | src/Services/ | 已实现,业务逻辑 |
-| ReloadGatewayAsync | src/Services/GatewayService.cs:340 | 空实现,需实现广播 |
+| ConfigNotificationService | src/Services/ | ✓ 已实现 PostgreSQL NOTIFY |
+| ReloadGatewayAsync | src/Services/GatewayService.cs | 待集成通知服务 |
### 待完成任务
-- 实现 ReloadGatewayAsync() 广播机制
-- 集成 Redis pub/sub
-- 实现 K8s 服务健康检查
+- 无
---
## 备注
-- Console 是运维中枢,网关配置的单一管理入口
-- Gateway 监听配置变更并重载
+- Console 是运维中枢,网关配置的单一管理门户
+- 广播策略:仅手动触发(通过 /reload 接口)
+- 下游网关收到通知后自行查询数据库刷新
---
-*最后更新:2026-03-02 初始化后*
+*最后更新:2026-03-03*
diff --git a/.planning/phases/01-gateway-config-management/01-CONTEXT.md b/.planning/phases/01-gateway-config-management/01-CONTEXT.md
new file mode 100644
index 0000000..4361f1f
--- /dev/null
+++ b/.planning/phases/01-gateway-config-management/01-CONTEXT.md
@@ -0,0 +1,75 @@
+# 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
new file mode 100644
index 0000000..1fcaee9
--- /dev/null
+++ b/.planning/phases/01-gateway-config-management/01-PLAN.md
@@ -0,0 +1,146 @@
+---
+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 操作自动触发广播
+- [ ] 编译通过
+
+
+
diff --git a/.planning/phases/01-gateway-config-management/01-SUMMARY.md b/.planning/phases/01-gateway-config-management/01-SUMMARY.md
new file mode 100644
index 0000000..ccf7e1d
--- /dev/null
+++ b/.planning/phases/01-gateway-config-management/01-SUMMARY.md
@@ -0,0 +1,83 @@
+# 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
new file mode 100644
index 0000000..2474732
--- /dev/null
+++ b/.planning/phases/02-gateway-plugin-system/02-SUMMARY.md
@@ -0,0 +1,27 @@
+# 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
new file mode 100644
index 0000000..e69de29
diff --git a/.planning/phases/03-gateway-config-broadcast/03-CONTEXT.md b/.planning/phases/03-gateway-config-broadcast/03-CONTEXT.md
new file mode 100644
index 0000000..f353f6a
--- /dev/null
+++ b/.planning/phases/03-gateway-config-broadcast/03-CONTEXT.md
@@ -0,0 +1,74 @@
+# 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
index ae5e741..a27d826 100644
--- a/.planning/phases/03-gateway-config-broadcast/03-PLAN.md
+++ b/.planning/phases/03-gateway-config-broadcast/03-PLAN.md
@@ -11,102 +11,102 @@ user_setup: []
must_haves:
truths:
- - "Existing broadcast mechanism documented"
- - "Route -> Service -> Downstream flow understood"
- - "Config change events verified working"
+ - "现有广播机制已文档化"
+ - "路由 -> 服务 -> 下游流程已理解"
+ - "配置变更事件已验证可用"
artifacts:
- path: ".planning/phases/03-gateway-config-broadcast/03-SUMMARY.md"
- provides: "Phase execution summary"
+ provides: "阶段执行摘要"
key_links: []
---
-Analyze and document the existing gateway configuration broadcast mechanism. Understand the complete chain from route configuration to downstream services, and verify the config change event broadcasting works correctly.
+分析和文档化现有的网关配置广播机制。理解从路由配置到下游服务的完整链路,并验证配置变更事件广播是否正常工作。
@.planning/phases/01-gateway-config-management/01-SUMMARY.md
@.planning/phases/01-gateway-config-management/01-PLAN.md
-## Existing Implementation (from Phase 1)
+## 现有实现(来自 Phase 1)
-The broadcast mechanism uses PostgreSQL NOTIFY:
-- **Channel:** `gateway_config_changed`
-- **Event types:** service, route, instance, gateway
-- **Actions:** create, update, delete, reload
-- **Service:** ConfigNotificationService.cs
-- **Integration:** GatewayService.cs triggers broadcast on all CRUD operations
+广播机制使用 PostgreSQL NOTIFY:
+- **通道:** `gateway_config_changed`
+- **事件类型:** service, route, instance, gateway
+- **操作:** create, update, delete, reload
+- **服务:** ConfigNotificationService.cs
+- **集成:** GatewayService.cs 在所有 CRUD 操作时触发广播
- Task 1: Analyze existing broadcast implementation
+ 任务 1: 分析现有广播实现
src/Services/ConfigNotificationService.cs, src/Services/GatewayService.cs
-Analyze the existing implementation to understand:
-1. How ConfigNotificationService works (PostgreSQL NOTIFY)
-2. How GatewayService triggers broadcasts on CRUD operations
-3. What event types and payloads are sent
+分析现有实现以了解:
+1. ConfigNotificationService 如何工作(PostgreSQL NOTIFY)
+2. GatewayService 如何在 CRUD 操作时触发广播
+3. 发送的事件类型和载荷是什么
-Read the source files and document the findings.
+阅读源代码并记录发现。
- Files exist and contain notification logic
+ 文件存在且包含通知逻辑
- Implementation analysis complete, findings documented
+ 实现分析完成,发现已记录
- Task 2: Map route -> service -> downstream flow
+ 任务 2: 绘制路由 -> 服务 -> 下游流程
-Document the complete configuration chain:
-1. How routes are defined in Console
-2. How routes map to services
-3. How services are discovered by downstream Gateway
-4. When config changes, how the broadcast reaches downstream
+文档化完整配置链路:
+1. 路由如何在 Console 中定义
+2. 路由如何映射到服务
+3. 下游 Gateway 如何发现服务
+4. 配置变更时,广播如何到达下游
-Reference existing code in src/Models/, src/Services/, src/Controllers/
+参考 src/Models/、src/Services/、src/Controllers/ 中的现有代码
- Flow documentation created
+ 流程文档已创建
- Configuration chain documented
+ 配置链路已文档化
- Task 3: Verify broadcast events work end-to-end
+ 任务 3: 验证广播端到端工作
-Verify the broadcast mechanism:
-1. Check if PostgreSQL LISTEN/NOTIFY is properly configured
-2. Verify ReloadGatewayAsync sends the correct event
-3. Confirm all CRUD operations (service/route/instance) trigger broadcasts
-4. Test end-to-end flow if possible
+验证广播机制:
+1. 检查 PostgreSQL LISTEN/NOTIFY 是否正确配置
+2. 验证 ReloadGatewayAsync 发送正确事件
+3. 确认所有 CRUD 操作(服务/路由/实例)都触发广播
+4. 如可能,测试端到端流程
- Build succeeds, API endpoints functional
+ 编译成功,API 端点可用
- Broadcast verification complete
+ 广播验证完成
-1. Read and analyze ConfigNotificationService.cs
-2. Read and analyze GatewayService.cs
-3. Document route -> service -> downstream flow
-4. Verify build passes
+1. 阅读并分析 ConfigNotificationService.cs
+2. 阅读并分析 GatewayService.cs
+3. 文档化路由 -> 服务 -> 下游流程
+4. 验证编译通过
-- [x] Existing broadcast implementation analyzed
-- [x] Configuration chain documented
-- [x] Broadcast events verified
-- [x] Summary created
+- [x] 现有广播实现已分析
+- [x] 配置链路已文档化
+- [x] 广播事件已验证
+- [x] 摘要已创建
diff --git a/Directory.Packages.props b/Directory.Packages.props
index b0c5c35..2cb65f2 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,7 +4,7 @@
-
+
diff --git a/src/Services/ConfigNotificationService.cs b/src/Services/ConfigNotificationService.cs
new file mode 100644
index 0000000..b6d3f92
--- /dev/null
+++ b/src/Services/ConfigNotificationService.cs
@@ -0,0 +1,133 @@
+using System.Text.Json;
+using Microsoft.Extensions.Logging;
+using Npgsql;
+using Fengling.Console.Data;
+using Microsoft.EntityFrameworkCore;
+
+namespace Fengling.Console.Services;
+
+///
+/// 配置变更通知服务接口
+///
+public interface INotificationService
+{
+ ///
+ /// 发布通知到指定通道
+ ///
+ Task PublishAsync(string channel, string payload, CancellationToken cancellationToken = default);
+
+ ///
+ /// 发布配置变更事件
+ ///
+ Task PublishConfigChangeAsync(
+ string eventType,
+ string action,
+ object? details = null,
+ CancellationToken cancellationToken = default);
+}
+
+///
+/// 配置变更事件数据
+///
+public class ConfigChangeEvent
+{
+ public string EventType { get; set; } = ""; // service, route, instance, gateway
+ public string Action { get; set; } = ""; // create, update, delete, reload
+ public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+ public object? Details { get; set; }
+}
+
+///
+/// PostgreSQL 通知服务实现
+/// 使用 PostgreSQL NOTIFY/LISTEN 机制广播配置变更
+///
+public class PgSqlNotificationService : INotificationService
+{
+ private readonly ILogger _logger;
+ private readonly string _connectionString;
+
+ public const string GatewayConfigChangedChannel = "gateway_config_changed";
+
+ public PgSqlNotificationService(DbContextOptions dbContextOptions, ILogger logger)
+ {
+ _logger = logger;
+
+ // 从 DbContextOptions 获取连接字符串
+ string? connectionString = null;
+
+ foreach (var ext in dbContextOptions.Extensions)
+ {
+ var extType = ext.GetType();
+ if (extType.Name.Contains("Npgsql"))
+ {
+ var prop = extType.GetProperty("ConnectionString");
+ if (prop != null && prop.PropertyType == typeof(string))
+ {
+ connectionString = prop.GetValue(ext) as string;
+ break;
+ }
+ }
+ }
+
+ _connectionString = connectionString
+ ?? throw new InvalidOperationException("DefaultConnection not configured");
+ }
+
+ ///
+ public async Task PublishAsync(string channel, string payload, CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ await using var connection = new NpgsqlConnection(_connectionString);
+ await connection.OpenAsync(cancellationToken);
+
+ await using var cmd = new NpgsqlCommand(
+ $"SELECT pg_notify(@channel, @payload)",
+ connection);
+
+ cmd.Parameters.AddWithValue("channel", channel);
+ cmd.Parameters.AddWithValue("payload", payload);
+
+ await cmd.ExecuteNonQueryAsync(cancellationToken);
+
+ _logger.LogInformation("Published notification to channel '{Channel}': {Payload}", channel, payload);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to publish notification to channel '{Channel}'", channel);
+ }
+ }
+
+ ///
+ /// 创建配置变更事件并发布
+ ///
+ public async Task PublishConfigChangeAsync(
+ string eventType,
+ string action,
+ object? details = null,
+ CancellationToken cancellationToken = default)
+ {
+ var configEvent = new ConfigChangeEvent
+ {
+ EventType = eventType,
+ Action = action,
+ Timestamp = DateTime.UtcNow,
+ Details = details
+ };
+
+ var payload = JsonSerializer.Serialize(configEvent);
+ await PublishAsync(GatewayConfigChangedChannel, payload, cancellationToken);
+ }
+}
+
+///
+/// 通知服务扩展方法
+///
+public static class NotificationServiceExtensions
+{
+ public static IServiceCollection AddNotificationService(this IServiceCollection services)
+ {
+ services.AddScoped();
+ return services;
+ }
+}