- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
本指南以 WuKongIM 仓库中的实施计划 docs/superpowers/plans/2026-05-12-channel-cluster-operations-p05.md 及其配套设计规范 docs/superpowers/specs/2026-05-12-channel-cluster-operations-p05-design.md 为主体,讲解在 P0 只读路径之上新增的两个"安全运维操作":真实的副本/运行时状态详情查询与策略驱动的 Leader 安全修复。读者将掌握:manager 三层架构(HTTP 适配层 → management usecase → runtime/pkg 端口)的正确依赖方向、use case 端口与 DTO 的划分、HTTP 路由与错误映射规则、前端 unhealthy 页面如何消费这些能力,以及该计划在仓库中的最终落地状态。
1. 计划背景:P0 只读路径之后的第一批安全操作
WuKongIM 的 Web 管理端(web/)在 P0 阶段已经完成了频道集群(Channel Cluster)的只读路径:集群总览/channel-cluster、频道列表/channel-cluster/list、异常频道/channel-cluster/unhealthy,对应的后端聚合 API(GET /manager/channel-cluster/summary、GET /manager/channel-cluster/unhealthy)也已完成。
P0.5 计划的目标是在这条只读路径之上,增加第一批安全的 manager 频道集群操作:
- 真实的副本/状态详情(truthful replica/status detail):查询一个频道的权威元数据 + 当前可证明的运行时状态,不虚构任何未经证明的数据;
- 策略驱动的 Leader 修复(policy-driven leader repair):通过后端既有的安全修复通道,对"无 Leader"的异常频道执行修复或校验。
该计划明确划定了两条红线(设计文档Scope中的 Out of scope):
- 不暴露显式目标 Leader 转移(
target_node_idtransfer)——它被推迟到 P0.6,需要运行时 repairer 先支持"指定候选 + dry-run 安全证明"作为一等端口; - 不推断 Follower 落后量(follower lag)——在没有可证明的 follower 运行时数据时,相关字段一律保持
null,绝不臆造。
这一"只报已证明事实"的保守原则贯穿了后端实现、HTTP DTO 与前端 UI 三层。
2. 架构约束:依赖方向与组合根
计划的架构约束是全文的核心骨架,也是后续所有任务(Task 1–7)都必须遵守的纪律:
internal/access/manager (HTTP 适配层,只调用 usecase,不直接碰 runtime / node RPC) │ ▼ internal/usecase/management (窄操作端口:ChannelReplicaStatusReader / ChannelLeaderRepairOperator) │ ▼ internal/runtime、pkg/channel (通过端口访问,具体实现由 internal/app 注入) ▲ │ internal/app (唯一的组合根 / composition root,接线具体实现)- manager HTTP 只是适配器:它只调用
internal/usecase/management,绝不直接调用 runtime 或 node RPC; - 窄 usecase 端口:为"运行时状态读取"和"安全 Leader 修复"定义最小化端口;
- 具体实现只从
internal/app接线:状态读取器来自app.channelLog.Status(当前节点的运行时路径),修复操作符来自build.go中已构建的 channelmeta leader repairer; - 前端保持薄客户端:
web/只是 API 的消费者,不持有任何业务决策。
技术栈(按计划文档):Go 1.23、Gin manager API、既有internal/runtime/channelmetaLeader repairer、React 19、TypeScript、React Router DOM 7、react-intl、Vitest、Bun/Vite。
3. Task 1:管理 usecase 的操作端口与 DTO
3.1 先读包级流程文档
实施的第一步是重新阅读相关包的流程文档,理解 repair 与运行时状态语义:
cat internal/runtime/channelmeta/FLOW.md cat pkg/channel/FLOW.md cat pkg/channel/replica/FLOW.md说明:计划撰写时这些文件存在于上述路径;当前仓库内部结构已随工程演进重组,
internal/runtime下的包已调整为channelappend、delivery、mqttsession等组织方式,读包级 FLOW 的意图是"动手前先理解语义边界",这一做法仍然适用。
3.2 两个窄操作端口
在internal/usecase/management的 App 选项与结构中新增两个带文档注释的端口:
type ChannelReplicaStatusReader interface { // ChannelRuntimeStatus returns the best proven runtime status for one channel. ChannelRuntimeStatus(ctx context.Context, id channel.ChannelID) (channel.ChannelRuntimeStatus, error) } type ChannelLeaderRepairOperator interface { // RepairChannelLeader repairs or validates authoritative channel leader metadata. RepairChannelLeader(ctx context.Context, req RepairChannelClusterLeaderRequest) (RepairChannelClusterLeaderResult, error) }并在Options与App中增加字段:
ChannelReplicaStatus ChannelReplicaStatusReader ChannelLeaderRepair ChannelLeaderRepairOperator命名上刻意避开了既有ChannelRuntimeMeta相关名称,防止与已有的元数据读取能力冲突。
从当前仓库看,
internal/usecase/management的App结构已演进为"分组依赖"模式(见 internal/usecase/management/nodes.go 中type App struct的nodeManagementDeps、channelManagementDeps、userManagementDeps、messageManagementDeps、operationsManagementDeps分组,以及New(opts Options)的注入方式)。P0.5 端口在落地时会以相同风格并入对应分组,本文保留计划中的原始接口形状,便于对照设计意图。
3.3 副本详情 DTO 与方法
计划定义了完整的副本详情 DTO(数值指针字段在未知时保持nil,HTTP 层序列化为null):
type ChannelClusterReplicaStatus struct { // NodeID is the replica node ID. NodeID uint64 // Role is "leader" or "follower" from authoritative metadata. Role string // IsLeader reports whether this replica is the authoritative leader. IsLeader bool // InISR reports whether this replica is in the authoritative ISR set. InISR bool // Reported reports whether live runtime status was proven for this replica. Reported bool // CommitSeq is the proven committed sequence for this replica, when known. CommitSeq *uint64 // LEO is the proven log end offset for this replica, when known. LEO *uint64 // CheckpointHW is the proven durable checkpoint high watermark, when known. CheckpointHW *uint64 // Lag is leader commit minus replica commit, when both are known. Lag *uint64 } type ChannelClusterReplicaDetail struct { // Channel is authoritative manager channel metadata. Channel ChannelRuntimeMetaDetail // RuntimeReported reports whether a runtime status source proved a live status. RuntimeReported bool // CommitSeq is the proven leader/local committed sequence, when known. CommitSeq *uint64 // MinAvailableSeq is the proven minimum readable sequence, when known. MinAvailableSeq *uint64 // RetentionThroughSeq is the proven retention boundary, when known. RetentionThroughSeq *uint64 // Replicas contains one row for each authoritative replica. Replicas []ChannelClusterReplicaStatus }方法签名与实现要点:
func (a *App) GetChannelClusterReplicaDetail(ctx context.Context, channelID string, channelType int64) (ChannelClusterReplicaDetail, error)- 先复用既有
a.GetChannelRuntimeMeta取得权威详情(该方法在当前仓库 internal/usecase/management/channel_runtime_meta.go 中有完整实现:校验 channelID/channelType、LocalControlSnapshot定位 Slot、GetChannelRuntimeMeta取行、再经managerChannelRuntimeMetaItems组装 DTO); - 若
a.channelReplicaStatus为nil,直接返回RuntimeReported=false的行且不报错; - 状态读取器返回
channel.ErrNotReady、channel.ErrStaleMeta、channel.ErrInvalidConfig时,一律视为"未报告状态"而非端点失败。
这里体现的语义是:只要权威元数据存在,端点就必须成功返回,运行时状态只是"能证明多少报多少"。
3.4 对应的测试:只报已证明的运行时状态
计划为该方法设计的测试用例TestGetChannelClusterReplicaDetailReportsOnlyProvenRuntimeStatus是理解保守策略的最佳样例:
- fake 权威元数据:channel
room-1,type2,slot9,leader1,replicas[1,2,3],ISR[1,2],MinISR2,状态 active,经 fake 消息读取器得到 max seq42; - fake 状态读取器返回
channel.ChannelRuntimeStatus{Leader: 1, HW: 42, CommittedSeq: 42, MinAvailableSeq: 1, RetentionThroughSeq: 0}。
断言内容:
Channel.HashSlot由 fake cluster 填充;RuntimeReported == true;CommitSeq、MinAvailableSeq、RetentionThroughSeq均非 nil 且与运行时状态一致;- 节点
1的行:Reported=true、IsLeader=true、Role="leader"、CommitSeq=42、Lag=0; - 节点
2、3的行:Reported=false、角色follower、未知数值指针全部为 nil。
这条用例精确锁定了"follower 未证明 → 不填数值"的行为。
4. Task 2:安全的 Leader 修复 usecase
4.1 修复请求/结果 DTO 与包级错误
type RepairChannelClusterLeaderRequest struct { // ChannelID identifies the channel to repair. ChannelID string // ChannelType identifies the channel type to repair. ChannelType int64 // Reason is the manager-facing reason that requested repair. Reason string } type RepairChannelClusterLeaderResult struct { // Changed reports whether authoritative metadata changed. Changed bool // Meta is authoritative metadata after repair or validation. Meta metadb.ChannelRuntimeMeta } type RepairChannelClusterLeaderResponse struct { // Changed reports whether authoritative metadata changed. Changed bool // Channel is authoritative manager metadata after repair or validation. Channel ChannelRuntimeMetaDetail }新增包级错误哨兵:
var ErrUnsupportedChannelClusterRepairReason = errors.New("management: unsupported channel cluster repair reason")方法签名:
func (a *App) RepairChannelClusterLeader(ctx context.Context, req RepairChannelClusterLeaderRequest) (RepairChannelClusterLeaderResponse, error)4.2 校验与原因映射规则
实现必须遵守以下规则:
- 参数校验:
ChannelID非空、ChannelType > 0; - 先读后修:修复前先加载当前 detail/meta;
- 允许修复的场景:
Reason为空且当前Leader==0,或Reason为ChannelClusterUnhealthyReasonNoLeader(即no_leader); - 拒绝的场景:单独以
isr_insufficient、status_not_active发起修复,一律返回ErrUnsupportedChannelClusterRepairReason——Leader 修复既不会补 ISR 成员,也不处理非 active 生命周期问题; - 操作符缺失:若 operator 为 nil,返回
channel.ErrInvalidConfig; - 结果转换:将返回的权威 meta 复用与
GetChannelRuntimeMeta相同的转换路径转为ChannelRuntimeMetaDetail(必要时抽小 helper 避免重复转换)。
4.3 三条修复测试用例
| 测试 | 场景 | 断言 |
|---|---|---|
TestRepairChannelClusterLeaderMapsNoLeaderToSafeRepair | 权威 metaLeader=0、replicas[1,2]、ISR[2];fake operator 记录请求并返回Leader=2、LeaderEpoch+1的新 meta | 响应Changed=true、返回 leader2、operator 收到no_leader(或实现中映射的运行时兼容原因) |
TestRepairChannelClusterLeaderSkipsISRInsufficientOnly | 已存在 Leader 的频道提交isr_insufficient | 返回metadb.ErrInvalidArgument或ErrUnsupportedChannelClusterRepairReason |
TestRepairChannelClusterLeaderReturnsNoSafeCandidate | fake operator 返回channel.ErrNoSafeChannelLeader | 错误原样保留 |
这三条用例分别锁定了"正确触发修复""拒绝不支持的原因""保留无安全候选错误"三类行为。
4.4 原因映射的语义(来自设计规范)
P0 的 unhealthy 原因是 manager 面向的字符串,而修复必须使用 runtime 的 channel leader repair 原因。设计规范明确:
no_leader→ 映射到既有的"缺失/死亡 Leader 修复策略"路径;isr_insufficient单独出现 →不显示修复按钮(Leader 修复不会新增 ISR 成员);status_not_active单独出现 →不显示修复按钮(非 active 生命周期不属于 Leader 修复问题)。
设计原则:不发明新的 runtime 原因,能复用既有原因就复用。
5. Task 3:暴露 Manager HTTP 操作路由
5.1 Management 接口扩展
在internal/access/manager/server.go的Management接口上增加两个方法(英文注释):
GetChannelClusterReplicaDetail(ctx context.Context, channelID string, channelType int64) (managementusecase.ChannelClusterReplicaDetail, error) RepairChannelClusterLeader(ctx context.Context, req managementusecase.RepairChannelClusterLeaderRequest) (managementusecase.RepairChannelClusterLeaderResponse, error)5.2 HTTP DTO(snake_case JSON)
internal/access/manager/channel_cluster_operations.go中定义:
type ChannelClusterReplicaDetailResponse struct { ... } type ChannelClusterReplicaStatusDTO struct { ... } type RepairChannelClusterLeaderRequestDTO struct { Reason string `json:"reason"` } type RepairChannelClusterLeaderResponseDTO struct { Changed bool `json:"changed"`; Channel ChannelRuntimeMetaDTO/Detail DTO }关键规则:指针数值字段在未知时必须编码为null。
5.3 路由注册与权限
读路由加入既有 channel cluster 读组:
channelCluster.GET("/channel-cluster/:channel_type/:channel_id/replicas", s.handleChannelClusterReplicas)写路由新建独立写组并挂写权限:
channelClusterWrites := s.engine.Group("/manager") if s.auth.enabled() { channelClusterWrites.Use(s.requirePermission("cluster.channel", "w")) } channelClusterWrites.POST("/channel-cluster/:channel_type/:channel_id/repair", s.handleChannelClusterRepair)GET .../replicas:需要cluster.channel的r(读)权限;POST .../repair:需要cluster.channel的w(写)权限;- 本计划不注册 Leader 显式转移路由(留给 P0.6)。
5.4 错误映射表
计划给出了完整的 HTTP 错误映射契约:
| 错误 | HTTP 状态码 |
|---|---|
metadb.ErrInvalidArgument | 400 |
metadb.ErrNotFound | 404 |
managementusecase.ErrUnsupportedChannelClusterRepairReason | 400 |
channel.ErrNoSafeChannelLeader | 409 |
slotLeaderAuthoritativeReadUnavailable/leaderConsistentReadUnavailable | 503 |
| 其他 | 500 |
对应 HTTP 测试场景(TestManagerChannelCluster(Operation|Replica|Repair)):
GET /manager/channel-cluster/2/room-1/replicas返回channel、runtime_reported、commit_seq与每副本reported字段;POST /manager/channel-cluster/2/room-1/repair携带{"reason":"no_leader"}返回changed与更新后的channel.leader;- 读路由开启鉴权时要求
cluster.channel的r; - 修复路由要求
cluster.channel的w; - 非法 channel type → 400;未找到 → 404;无安全候选 → 409;Leader 不可用 → 503。
5.5 完整的 HTTP 响应形状(来自设计规范)
GET /manager/channel-cluster/2/room-1/replicas:
{ "channel": { "channel_id": "room-1", "channel_type": 2, "slot_id": 9, "hash_slot": 123, "channel_epoch": 7, "leader_epoch": 3, "leader": 1, "replicas": [1, 2, 3], "isr": [1, 2], "min_isr": 2, "max_message_seq": 42, "status": "active", "features": 0, "lease_until_ms": 0 }, "runtime_reported": true, "commit_seq": 42, "min_available_seq": 1, "retention_through_seq": 0, "replicas": [ { "node_id": 1, "role": "leader", "is_leader": true, "in_isr": true, "reported": true, "commit_seq": 42, "leo": null, "checkpoint_hw": null, "lag": 0 }, { "node_id": 2, "role": "follower", "is_leader": false, "in_isr": true, "reported": false, "commit_seq": null, "leo": null, "checkpoint_hw": null, "lag": null } ] }注意该示例的精髓:Leader 节点reported=true且有数值;follower 节点reported=false,commit_seq/leo/checkpoint_hw/lag全部为null——这就是"真实详情"的 HTTP 化表达。
POST /manager/channel-cluster/2/room-1/repair,请求体:
{ "reason": "no_leader" }响应体(修复成功,Leader 从 1 变为 2,LeaderEpoch 从 3 变为 4):
{ "changed": true, "channel": { "channel_id": "room-1", "channel_type": 2, "slot_id": 9, "hash_slot": 123, "channel_epoch": 7, "leader_epoch": 4, "leader": 2, "replicas": [1, 2, 3], "isr": [2, 3], "min_isr": 2, "max_message_seq": 42, "status": "active", "features": 0, "lease_until_ms": 1780000000000 } }6. Task 4:从internal/app接线
app 层负责把窄端口接到既有的本地对象上,不创建任何新的全局服务。
6.1 状态读取适配器
type managerChannelReplicaStatusReader struct { channelLog interface { Status(channel.ChannelID) (channel.ChannelRuntimeStatus, error) } } func (r managerChannelReplicaStatusReader) ChannelRuntimeStatus(ctx context.Context, id channel.ChannelID) (channel.ChannelRuntimeStatus, error) { if r.channelLog == nil { return channel.ChannelRuntimeStatus{}, channel.ErrInvalidConfig } return r.channelLog.Status(id) }测试要点:状态适配器把app.channelLog.Status结果作为channel.ChannelRuntimeStatus返回;channel.ErrNotReady穿透不包装。
6.2 修复适配器
type managerChannelLeaderRepairOperator struct { repairer runtimechannelmeta.Repairer // 或 AuthoritativeRepairer 兼容接口 }修复适配器调用既有runtime/channelmeta的AuthoritativeRepairer/repairer,返回变更后的 meta。计划还给出一个边界优化建议:如果调用的是RepairIfNeeded,则 usecase 可以直接传 meta 与 reason 而非仅请求形状,具体取决于边界是否更清晰,保持具体接线留在 app 层。
6.3 注入 Options
在internal/app/build.go创建managementusecase.New时注入:
ChannelReplicaStatus: managerChannelReplicaStatusReader{channelLog: app.channelLog}, ChannelLeaderRepair: managerChannelLeaderRepairOperator{repairer: channelLeaderRepairer},接线测试覆盖:manager 启用时 management app 收到非 nil 的 channel cluster 操作(设计规范 Testing 节)。
7. Task 5:前端 API 契约
7.1 TypeScript DTO
在web/src/lib/manager-api.types.ts增加:
export type ManagerChannelClusterReplicaStatus = { node_id: number role: string is_leader: boolean in_isr: boolean reported: boolean commit_seq?: number | null leo?: number | null checkpoint_hw?: number | null lag?: number | null } export type ManagerChannelClusterReplicaDetailResponse = { channel: ManagerChannelRuntimeMetaDetailResponse runtime_reported: boolean commit_seq?: number | null min_available_seq?: number | null retention_through_seq?: number | null replicas: ManagerChannelClusterReplicaStatus[] } export type RepairChannelClusterLeaderInput = { reason?: string } export type ManagerChannelClusterRepairResponse = { changed: boolean channel: ManagerChannelRuntimeMetaDetailResponse }7.2 API 包装函数
在web/src/lib/manager-api.ts增加:
export function getChannelClusterReplicas(channelType: number, channelId: string) { return jsonManagerFetch<ManagerChannelClusterReplicaDetailResponse>( `/manager/channel-cluster/${channelType}/${encodeURIComponent(channelId)}/replicas`, ) } export function repairChannelClusterLeader( channelType: number, channelId: string, input: RepairChannelClusterLeaderInput = {}, ) { return jsonManagerFetch<ManagerChannelClusterRepairResponse>( `/manager/channel-cluster/${channelType}/${encodeURIComponent(channelId)}/repair`, { method: "POST", body: JSON.stringify(input) }, ) }注意channelId必须经过encodeURIComponent,防止含特殊字符的频道 ID 破坏路径。
7.3 客户端测试断言
await getChannelClusterReplicas(2, "room-1") // fetch called with "/manager/channel-cluster/2/room-1/replicas" await repairChannelClusterLeader(2, "room-1", { reason: "no_leader" }) // fetch called with method POST, JSON body { reason: "no_leader" }同时断言ManagerApiError能把修复接口的 409 正确映射为错误对象。
8. Task 6:unhealthy 页面的详情与修复交互
8.1 详情面板状态
在web/src/pages/channel-cluster/unhealthy/page.tsx增加局部状态:
type DetailState = { channel: ManagerChannelClusterUnhealthyItem | null detail: ManagerChannelClusterReplicaDetailResponse | null loading: boolean error: Error | null }UI 使用表格下方的内联SectionCard或既有DetailSheet,保持简单。
8.2 检查副本动作
每一行新增按钮:
<Button onClick={() => void loadReplicaDetail(channel)} size="sm" variant="outline"> {intl.formatMessage({ id: "channelCluster.unhealthy.inspectReplicas" })} </Button>详情面板展示:channel ID/type、slot、leader、ISR、min ISR;若runtime_reported则展示运行时 commit 序列;每副本一行展示Reported/Not reported,未知数值一律渲染为-。
8.3 修复 Leader 动作(只对 no_leader 行)
function canRepairLeader(channel: ManagerChannelClusterUnhealthyItem) { return channel.reasons.includes("no_leader") }点击后:
- 调用
repairChannelClusterLeader(channel.channel_type, channel.channel_id, { reason: "no_leader" }); - 用返回的
changed与channel.leader展示结果文案; - 调用
loadFirstPage(true)刷新异常列表第一页。
只含isr_insufficient的行不显示修复按钮;修复 409 时展示"无安全候选"这类非破坏性冲突文案并保留该行可见;详情 503 在面板中映射为不可用状态。
8.4 新增 i18n 文案键
计划要求同时在web/src/i18n/messages/en.ts与zh-CN.ts增加以下键:
channelCluster.unhealthy.inspectReplicaschannelCluster.unhealthy.repairLeaderchannelCluster.unhealthy.repairSuccessChangedchannelCluster.unhealthy.repairSuccessUnchangedchannelCluster.unhealthy.repairConflictchannelCluster.replicaDetail.titlechannelCluster.replicaDetail.runtimeReportedchannelCluster.replicaDetail.runtimeUnreportedchannelCluster.replicaDetail.reportedchannelCluster.replicaDetail.notReportedchannelCluster.replicaDetail.commitSeqchannelCluster.replicaDetail.lag
8.5 页面测试矩阵
| 场景 | 断言 |
|---|---|
点击Inspect replicas | 加载并展示详情:Runtime reported、Node 1/leader/Reported/commit 42/lag 0、Node 2/follower/Not reported/- |
行含no_leader | 显示Repair leader;仅含isr_insufficient的行不显示 |
| 修复成功 | 以{ reason: "no_leader" }调用 API,展示 changed/leader 文案,并重载第一页 |
| 修复 409 | 展示No safe leader candidate冲突文案且行保持可见 |
| 详情 503 | 详情面板映射为不可用状态 |
9. Task 7:文档更新与全量验证
9.1 文档落笔
- docs/raw/web-admin-restructure.md:将
GET /manager/channel-cluster/:type/:id/replicas标记为"best-effort/proven 状态"已完成;POST /manager/channel-cluster/:type/:id/repair标记为"策略驱动修复"已完成;显式目标转移与批量 Leader drain 保持 pending; - web/README.md:更新
/channel-cluster/unhealthy的页面/API 矩阵,纳入 replicas 与 repair 端点。
9.2 验证命令序列
后端聚焦验证:
GOWORK=off go test ./internal/usecase/management ./internal/access/manager ./internal/app -count=1前端聚焦验证(manager API 客户端 + unhealthy 页 + 关联页回归):
cd web && bun run test src/lib/manager-api.test.ts src/pages/channel-cluster/unhealthy/page.test.tsx src/pages/channel-cluster/page.test.tsx src/pages/dashboard/page.test.tsx前端构建(不提交web/dist的 hash 变更,除非仓库约定要求恢复生成索引 hash):
cd web && bun run build更广泛的后端回归:
GOWORK=off go test ./internal/... ./pkg/... -count=19.3 最终验收标准(Final Acceptance Criteria)
GET /manager/channel-cluster/:type/:id/replicas返回真实的 reported/unreported 副本详情,且有 usecase 与 HTTP 测试覆盖;POST /manager/channel-cluster/:type/:id/repair触发安全的策略驱动 Leader 修复,且有 usecase 与 HTTP 测试覆盖;- 修复路由受
cluster.channel写权限保护; - unhealthy 页面可检查副本详情并修复
no_leader行; - UI 永不展示显式目标转移或臆造的 follower lag;
- 聚焦 Go 测试、聚焦 Web 测试、前端构建、更广泛后端测试均已运行并记录结果。
9.4 源码佐证:错误哨兵与状态 DTO
计划中反复引用的channel.ErrNotReady、channel.ErrStaleMeta等错误哨兵在当前仓库 pkg/channel/errors.go 中有明确定义(ErrNotReady = errors.New("channel: not ready")、ErrStaleMeta = errors.New("channel: stale meta")等),并有 pkg/channel/errors_test.go 对错误文本与 legacy 文本匹配做回归锁定。而ChannelRuntimeMetaDTO、GetChannelRuntimeMeta方法、状态字符串映射(managerChannelRuntimeStatus)、降级判定(managerChannelRuntimeDegraded,min_isr_not_met/isr_below_replicas)均可直接在 internal/usecase/management/channel_runtime_meta.go 中读到,它们是 P0.5 副本详情 DTO 中Channel部分的直接数据来源。
10. 计划的落地状态与后续路线
从 docs/raw/web-admin-restructure.md 的状态标记可以确认 P0.5 的最终落地情况(该文档同时记录了后续 P0.6 的完成状态):
- P0.5 — 频道集群操作(已完成安全子集)
- 副本详情读取:
GET /manager/channel-cluster/:type/:id/replicas已暴露权威元数据与已证明的 leader/local runtime 状态;未证明的 follower 数值保持 unknown/null; - 安全修复:
POST /manager/channel-cluster/:type/:id/repair已接入internal/usecase/management与既有 channelmeta leader repairer;当前 UI 仅对no_leader行显示修复。
- 副本详情读取:
- P0.6 — 频道集群显式 Leader 转移(已完成单频道安全子集)
POST /manager/channel-cluster/:type/:id/leader/transfer已暴露,目标节点必须是副本、在 ISR 中,且由后端通过既有 promotion evaluation 证明可安全成为 Leader。对应实施计划见 docs/superpowers/plans/2026-05-12-channel-cluster-leader-transfer-p06.md 与设计规范 docs/superpowers/specs/2026-05-12-channel-cluster-leader-transfer-p06-design.md。
- 待实现:
POST /manager/channel-cluster/batch/leader-drain/:node_id(批量迁移某节点上所有频道的 Leader,后续批量编排,复用单频道安全 transfer 原语)。
11. 要点小结
P0.5 实施计划为我们提供了一个可复用的"安全运维功能落地范式":
- 能力边界先行:先划定 in-scope / out-of-scope,把"显式转移"和"臆造 follower lag"挡在门外,用
null与reported=false表达"未证明"; - 依赖方向纪律:access 只调 usecase,usecase 只依赖窄端口,具体接线全在 app 组合根,保证架构可测试、可替换;
- TDD 逐片推进:每个 slice 先写失败测试(RED)再实现(GREEN),再聚焦回归,最后提交;
- 错误映射契约化:400/404/409/503/500 与具体错误哨兵一一对应,前后端契约一致;
- 前端只做消费:unhealthy 页面只根据
reasons.includes("no_leader")决定是否展示修复入口,不做任何业务推断。
对于需要在 WuKongIM 上继续扩展管理端操作(例如批量编排、审计日志)的开发者,本文所展示的端口划分、原因映射与验证纪律,正是下一批功能(P0.6+)可以沿用的骨架。
- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
相关推荐
StarRocks 副本管理完全指南:多副本写入、自动修复与共享数据集群恢复
StarRocks 副本管理完全指南:多副本写入、自动修复与共享数据集群恢复 数据副本是 StarRocks 保证高可用与数据安全的核心机制。本指南以 Star
数据库OLAP数据仓库大数据湖仓一体数据分析大麦自动抢票工具使用指南:网页与App双端配置,开抢毫秒级自动下单
大麦自动抢票工具使用指南:网页与App双端配置,开抢毫秒级自动下单 倒计时归零的那一刻,你如果还在手动选场次、挑票价,"立即购买"按钮早就点不上了。ticket
RPAWuKongIM Channel Leader 稳定性修复:从"跟随 Slot 拓扑"到"活性驱动的权威 Leader 语义"
WuKongIM Channel Leader 稳定性修复:从"跟随 Slot 拓扑"到"活性驱动的权威 Leader 语义" 导读 本文围绕 WuKongIM
即时通讯后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考