chore: 更新 Fengling.Platform.Infrastructure 到 1.0.12

This commit is contained in:
movingsam 2026-03-04 10:19:07 +08:00
parent b787fcc415
commit e05e10df95
11 changed files with 623 additions and 76 deletions

View File

@ -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 — 实施计划

View File

@ -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*

View File

@ -0,0 +1,75 @@
# Phase 1: 实现 Gateway 配置管理及事件推送 - Context
**收集日期:** 2026-03-02
**状态:** Ready for planning
**来源:** Manual planning (gsd-tools not available)
**更新:** 2026-03-03 - 添加数据源决策
<domain>
## Phase Boundary
实现 Console 管理 Gateway 配置的完整能力,包括:
- Gateway 配置的 CRUD 操作(已大部实现)
- 配置变更事件推送(待实现)
- 下游 Gateway 监听配置变更并重载
**现有能力:**
- GatewayController: API 端点已实现
- GatewayService: 业务逻辑已实现
- DTOs: 数据传输对象已定义
**待实现:**
- ReloadGatewayAsync() 广播机制
- 配置变更时自动触发广播
</domain>
<decisions>
## 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
</decisions>
<specifics>
## 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可复用
</specifics>
<deferred>
## Deferred Ideas
- K8s 服务健康检查(后续 Phase
- Redis pub/sub如果 PostgreSQL NOTIFY 方案不够用再考虑)
</deferred>
---
*Phase: 01-gateway-config-management*
*Context gathered: 2026-03-02, updated 2026-03-03*

View File

@ -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"
---
<objective>
实现配置变更广播机制,使下游 Gateway 能够监听到配置变更。
</objective>
<context>
@.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
</context>
<tasks>
<task type="auto">
<name>Task 1: 修改 ConfigNotificationService 使用 DbContext 获取连接字符串</name>
<files>src/Services/ConfigNotificationService.cs</files>
<action>
修改现有的 PgSqlNotificationService 实现:
1. 修改构造函数:
- 注入 ConsoleDbContext而非使用 IConfiguration
- 使用 DbContext.Database.GetConnectionString() 获取连接字符串
2. 移除:
- IConfiguration 依赖
- _configuration.GetConnectionString("DefaultConnection")
3. 示例代码:
```csharp
public PgSqlNotificationService(
ConsoleDbContext dbContext,
ILogger<PgSqlNotificationService> logger)
{
_connectionString = dbContext.Database.GetConnectionString()
?? throw new InvalidOperationException("DefaultConnection not configured");
_logger = logger;
}
```
4. 在 Program.cs 中注册服务时传入 DbContext
```csharp
services.AddScoped<INotificationService>(sp =>
new PgSqlNotificationService(
sp.GetRequiredService<ConsoleDbContext>(),
sp.GetRequiredService<ILogger<PgSqlNotificationService>>()));
```
</action>
<verify>
<automated>dotnet build --no-restore 2>&1 | head -20</automated>
</verify>
<done>PgSqlNotificationService 已修改为使用 DbContext 获取连接字符串</done>
</task>
<task type="auto">
<name>Task 2: 修改 GatewayService 集成通知服务</name>
<files>src/Services/GatewayService.cs</files>
<action>
修改 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": { ... }
}
```
</action>
<verify>
<automated>dotnet build --no-restore 2>&1 | head -30</automated>
</verify>
<done>GatewayService 集成通知服务,所有配置变更操作自动触发广播</done>
</task>
</tasks>
<verification>
整体验证:
1. dotnet build 编译通过
2. 手动调用 POST /api/console/gateway/reload 返回成功
3. PostgreSQL 数据库能收到 NOTIFY 消息
</verification>
<success_criteria>
- [x] ConfigNotificationService 改为使用 DbContext 获取连接字符串
- [ ] INotificationService 接口定义完成
- [ ] PgSqlNotificationService 实现完成
- [ ] GatewayService 集成通知服务
- [ ] ReloadGatewayAsync 触发广播
- [ ] CRUD 操作自动触发广播
- [ ] 编译通过
</success_criteria>
<output>
完成后创建 .planning/phases/01-gateway-config-management/01-SUMMARY.md
</output>

View File

@ -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<ConsoleDbContext>` 获取连接字符串(而非直接从配置文件读取)
- 通过反射从 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*

View File

@ -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*

View File

@ -0,0 +1,74 @@
# Phase 3: 网关配置变更广播机制 - Context
**Gathered:** 2026-03-03
**Status:** Ready for planning
<domain>
## Phase Boundary
分析现有的网关配置广播机制,梳理路由→服务→下游的完整链路,确定配置变更时的广播策略。
</domain>
<decisions>
## 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 手动触发的具体实现方式
- 广播失败时的错误处理策略
- 日志记录细节
</decisions>
<code_context>
## Existing Code Insights
### Reusable Assets
- ConfigNotificationService.cs: PostgreSQL NOTIFY 机制已实现
- INotificationService 接口: 可直接复用
### Established Patterns
- 使用 PgSqlNotificationService 发布通知
- 通道名称: `gateway_config_changed`
### Integration Points
- GatewayService 需注入 INotificationService
- ReloadGatewayAsync 需调用通知服务
</code_context>
<specifics>
## Specific Ideas
- 事件 payload 尽量精简,只传递 "reload" action
- 下游网关监听同一数据库连接,收到 NOTIFY 后刷新
</specifics>
<deferred>
## Deferred Ideas
- 自动触发广播(未来可选优化)
</deferred>
---
*Phase: 03-gateway-config-broadcast*
*Context gathered: 2026-03-03*

View File

@ -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: []
---
<objective>
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.
分析和文档化现有的网关配置广播机制。理解从路由配置到下游服务的完整链路,并验证配置变更事件广播是否正常工作。
</objective>
<context>
@.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 操作时触发广播
</context>
<tasks>
<task type="auto">
<name>Task 1: Analyze existing broadcast implementation</name>
<name>任务 1: 分析现有广播实现</name>
<files>src/Services/ConfigNotificationService.cs, src/Services/GatewayService.cs</files>
<action>
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.
阅读源代码并记录发现。
</action>
<verify>
<automated>Files exist and contain notification logic</automated>
<automated>文件存在且包含通知逻辑</automated>
</verify>
<done>Implementation analysis complete, findings documented</done>
<done>实现分析完成,发现已记录</done>
</task>
<task type="auto">
<name>Task 2: Map route -> service -> downstream flow</name>
<name>任务 2: 绘制路由 -> 服务 -> 下游流程</name>
<files></files>
<action>
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/ 中的现有代码
</action>
<verify>
<automated>Flow documentation created</automated>
<automated>流程文档已创建</automated>
</verify>
<done>Configuration chain documented</done>
<done>配置链路已文档化</done>
</task>
<task type="auto">
<name>Task 3: Verify broadcast events work end-to-end</name>
<name>任务 3: 验证广播端到端工作</name>
<files></files>
<action>
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. 如可能,测试端到端流程
</action>
<verify>
<automated>Build succeeds, API endpoints functional</automated>
<automated>编译成功API 端点可用</automated>
</verify>
<done>Broadcast verification complete</done>
<done>广播验证完成</done>
</task>
</tasks>
<verification>
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. 验证编译通过
</verification>
<success_criteria>
- [x] Existing broadcast implementation analyzed
- [x] Configuration chain documented
- [x] Broadcast events verified
- [x] Summary created
- [x] 现有广播实现已分析
- [x] 配置链路已文档化
- [x] 广播事件已验证
- [x] 摘要已创建
</success_criteria>
<output>
After completion, create `.planning/phases/03-gateway-config-broadcast/03-SUMMARY.md`
完成后创建 `.planning/phases/03-gateway-config-broadcast/03-SUMMARY.md`
</output>

View File

@ -4,7 +4,7 @@
</PropertyGroup>
<ItemGroup>
<!-- Microsoft Packages -->
<PackageVersion Include="Fengling.Platform.Infrastructure" Version="1.0.11" />
<PackageVersion Include="Fengling.Platform.Infrastructure" Version="1.0.12" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.2" />

View File

@ -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;
/// <summary>
/// 配置变更通知服务接口
/// </summary>
public interface INotificationService
{
/// <summary>
/// 发布通知到指定通道
/// </summary>
Task PublishAsync(string channel, string payload, CancellationToken cancellationToken = default);
/// <summary>
/// 发布配置变更事件
/// </summary>
Task PublishConfigChangeAsync(
string eventType,
string action,
object? details = null,
CancellationToken cancellationToken = default);
}
/// <summary>
/// 配置变更事件数据
/// </summary>
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; }
}
/// <summary>
/// PostgreSQL 通知服务实现
/// 使用 PostgreSQL NOTIFY/LISTEN 机制广播配置变更
/// </summary>
public class PgSqlNotificationService : INotificationService
{
private readonly ILogger<PgSqlNotificationService> _logger;
private readonly string _connectionString;
public const string GatewayConfigChangedChannel = "gateway_config_changed";
public PgSqlNotificationService(DbContextOptions<ConsoleDbContext> dbContextOptions, ILogger<PgSqlNotificationService> 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");
}
/// <inheritdoc/>
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);
}
}
/// <summary>
/// 创建配置变更事件并发布
/// </summary>
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);
}
}
/// <summary>
/// 通知服务扩展方法
/// </summary>
public static class NotificationServiceExtensions
{
public static IServiceCollection AddNotificationService(this IServiceCollection services)
{
services.AddScoped<INotificationService, PgSqlNotificationService>();
return services;
}
}