资讯动态

WuKongIM v2→v3 迁移中的插件运行时验收与配置决策

发布时间:2026/10/17 2:20:42 来源:尧图企业网站定制
即时通讯后端【免费下载链接】WuKongIMMore than just IM 不只是即时通讯(IM)项目地址https://gitcode.com/gh_mirrors/wu/WuKongIM点击查看免费下载导读本文以 WuKongIM 仓库中docs/superpowers/reports/2026-09-07-v2-migration-plugin-runtime.md验收记录为骨架完整还原 v2→v3 迁移过程中对wk.plugin.ai-example插件的运行时验收过程、隔离测试设计以及统一采用源节点 1001 配置这一决策背后的技术推导与实现细节。读完本文你将理解插件离线 Receive 执行器节点的选择如何影响回复内容、迁移计划中plugin_configs覆盖策略的语义与校验规则以及为什么这份验收证据仍不足以打开cutover_ready门禁。背景为什么插件运行时验收独立于数据迁移v2→v3 迁移不只是把表数据搬到新存储。对绑定用户的离线 AI 插件而言迁移必须同时证明原插件绑定PluginUser在原生 v3 集群中仍能被正确查询、插件仍能被正常调度并产生回复、回复可持久化读取、且在完整重启后历史不丢失。2026-09-07 的这份运行时验收报告工作树codex/v2-v3-migration正是围绕这条链路做的一次隔离组件级验证。报告记录了一个关键事实在验收前节点本地配置 1001→1、1002→2、1003→3 已被批准保留了节点本地配置名但运行时验收暴露了该配置没有解决的问题——回复内容中的名字不统一。这直接推动了后续统一 source-1001 配置的决策。验收设计与输入隔离验收测试TestMigrationPluginBindingsInNativeThreeNodeCluster位于 internal/app/migration_plugin_cluster_integration_test.gointegration构建标签下被刻意设计为只含插件绑定范围的组件夹具而不是全量源迁移证明源码固定钉在a888f89533d0e7d1b2030e06504ca97f1ad891d4父捕获 digest 为3780b1757dbba3b6e46bf2c750bcaec1c09d7b65d974f586d365e2f893d5a896。私有组件夹具恰好包含 9 行捕获的 PluginUser 行每个原节点 1 条主行 2 条索引行所有 3 条主字段 digest 都匹配62ddf9a60db1d99a6c79844ef59b426e94a226295ff32e7cab3d9678d45d4967。集成测试中同样对每行主行字段做 SHA-256 核对测试代码第 84-88 行。原可执行文件 SHA-256 为671b3436d1a8d765371077009b1dfd6dec4528a1ce9cdc0dbebe2cfddc5b3224。测试把这串字节原样复制为wk.plugin.ai-example.wkpv3 默认扫描器从文件名推导插件标识旧的-linux-amd64平台后缀不属于注册的插件编号测试代码第 143-147 行的注释与此一致。运行环境是测试主机上的临时 Docker 容器无外网、只读根、只读输入挂载、无 Linux capabilities、2 CPU 配额、1536 MiB 内存、512 MiB 可执行临时文件系统三个应用节点仅在回环接口上通信。程序、配置与绑定文件均为私有报告不含任何真实 UID 或配置值。组件的工作方式使用原源快照检查拓扑与 Slot 进度校验原索引选择正式副本转换 1 条逻辑绑定安装 3 个原生副本并在启动目标集群前独立校验它们。报告特别强调组件捕获 digest 刻意区别于全源捕获不是全源 PREPARED 或 cutover 证书生产准备流程中的插件注册/配置门禁一个都没有被跳过。两种配置候选的验收结果每个配置候选都完整跑完三阶段直接离线 hook、普通消息发送触发自动 Receive、整集群关闭重启后再验证。每轮 6 个直接离线 hook 用例在三个节点上分别对个人/群组消息调用离线 hook走真实集群绑定读取与真实提交回复。每轮 6 个普通消息发送用例个人/群组发送进入任一节点都会自动触发离线 Receive插件回复经正常消息 usecase 返回并可持久化读取。完整关停并重启集群重启后重复同样的绑定/配置检查并在全新频道上追加 12 个用例。即每个配置候选共 24 条已提交的插件回复其中 12 条为提交后的自动回复。测试不声称恢复了早期频道的完整历史——该历史恢复阻塞项被单独记录仍处于打开状态网关/SDK 投递、在线客户端状态、故障切换、任意插件方法与生产流量都不在本有界测试范围内。候选一保留节点本地配置原每节点各自配置候选在 27.70 秒通过。其 12 条自动回复使用了全部三种配置名目标配置 1 出现 3 次、配置 2 出现 6 次、配置 3 出现 3 次。即使绑定的是同一个 UID不同频道也由不同执行器节点处理——这正是下一节要解释的机制差异。候选二统一 source-1001 配置统一候选在 27.39 秒通过全部 12 条自动回复都匹配源 1001 配置的名字。该候选只改变每个目标的有效 config值每个目标原有的期望状态身份、启用标志与时间戳全部保留已批准的原分配与原源数据保持不变。配套单测与两个环境问题聚焦的应用插件/离线观察者单元测试同样通过。初跑时发现两个环境问题Docker 默认临时挂载导致暂存文件无法执行、零值应用配置遗漏了 Delivery 设置。通过显式临时执行权限与正常的 product delivery 配置解决未改动任何服务端运行时或存储代码。为什么配置决策是实质性的执行器节点决定回复内容报告基于钉住的原始源pinned original sources给出了这条调用链internal/manager/manager_tag.go:calcUsersInNode把用户分配到其 UID Slot 的 Leaderinternal/channel/handler/event_distribute.go:distributeByTag转发到这些节点并为接收者排队离线事件internal/pusher/handler/event_pushoffline.go:pushOffline在该节点上通过processAIPush调用绑定插件。说明以上三条路径是文档记录的 v2 原源pinned original sources路径当前仓库为 v3 代码搜索不到同名文件v3 中对应的投递与离线机制实现于 internal/runtime/delivery/runtime.godurable 计划才产生离线效果见 internal/runtime/delivery/FLOW.md与 internal/usecase/plugin/receive.goReceiveOffline调用绑定插件。捕获的绑定用户 UID 哈希到源 Slot 36其 Leader 是节点 1001。因此在该捕获的、稳定的拓扑下源 1001 就是预期执行器。文档明确这是代码与快照推断不是重放已停机的生产服务器也不声称每条历史回复都使用同一节点。PluginUser 存储本身属于 Slot 0这一独立的存储权威不应与 Receive 执行亲缘性混为一谈。v3 的投递运行时从执行投递计划的进程发出离线效果internal/runtime/delivery/runtime.go 中 durable 计划收集离线 UID 并通过OfflineRecipientsObserver通知。观察到的混合名字回复证实了这一差异对该插件的影响——该插件把config.name嵌入回复负载集成测试第 296-301 行按我是%s,收到您的消息hello匹配回复者名字。此前批准的 1001→1、1002→2、1003→3 保留了节点本地配置但没有解决这个新暴露的回复内容变化问题。用户随后批准该插件在全部三个目标上统一使用源 1001 的有效配置。该决策不改变任何 v3 存储或调度逻辑。统一 source-1001 配置策略的实现与校验配置策略细节记录在 2026-09-07-v2-migration-plugin-config-policy.md。实现位于 internal/usecase/migration/plugin_settings.go。计划表示保留既有plugin_nodes分配 1001→1、1002→2、1003→3新增plugin_configs: [ {plugin_no: wk.plugin.ai-example, source_node: 1001} ]对应的 Go 类型是 plugin_settings.go 第 24-29 行 的PluginConfigMapping只覆盖有效配置绝不触碰接收节点的注册、启用标志与时间戳。语义与校验规则validatePluginNodes只有该插件的有效 Config 改变每个目标保留其原始映射节点的启用状态与精确期望状态时间戳未列出的插件保留其映射源配置。选中源与插件必须存在且插件必须在每个映射源节点上注册重复、未知、不安全或不完整的选择直接失败插件设置仍需完整的源节点→目标节点双射plugin_settings.go 第 60-97 行。prepare 与归档重建都从原始行推导分配私有记录保留原字段、源行 key/digest 与所选配置的源 key/digest报告不含任何配置值。该策略改变计划 digest旧工作区/归档不能作为新计划的工件复用。import 在发布代次指纹前调用未改动的原生插件 Store 写入data_dir/plugin-state精确重试保留文件变更文件被拒绝包括无 READY 检查点的中断代次。离线验证独立地再次解码原始 Plugin 行并应用计划不读取转换后的设置检查 JSON 时避免 float64 舍入核对启用标志、时间戳、缺失/多余文件与计数有界目录枚举拒绝符号链接、损坏文件与意外条目证据在磁盘工作区中有序排列保证 digest 可复现。CLI 同时接通原生 import 与源派生验证plugin_settings验证报告携带自身源绑定 digest其成功从不设置cutover_ready。PreparePluginSettingsplugin_settings.go 第 104-242 行从捕获行重建每条记录读取各源节点 Plugin 主行 → 解码业务事实 → 构造DesiredState→ 以captureplansource nodeplugin no为 key 落盘 → 按映射为目标节点指派 → 对配置覆盖的插件从指定源行取出原始 Config 替换 → 校验覆盖插件必须存在于每个映射源节点 → 计算可复现的 settings digest。回归验证13 类故障场景internal/usecase/migration/plugin_profile_test.go 的TestReceiveProfileRejectsUnverifiedContractChanges用一张表覆盖 13 类故障注入valid、binary、profile、missing-program、unmapped-program、competition、unapproved-config、source-version、method、priority、version、status、config-key、config-type、legacy-config。除valid外全部必须失败——包括改可执行文件 SHA-256、声明未验证的 profile、删程序、改方法/优先级/版本/状态、给配置加键、把配置类型改成null、用旧版大写Name键等。unapproved-config场景未提供配置映射也会失败证明运行时验收不能绕过配置门禁。配置策略回归命令来自策略报告实测包耗时 usecase 6.449 s、v2 适配器 110.194 s、v3 适配器 11.194 sGOWORKoff go test ./internal/usecase/migration ./internal/infra/migrationv2 \ ./internal/infra/migrationv3 ./internal/app/migration \ ./internal/access/migratecli ./cmd/wkmigrate -count1真实捕获配置核对策略报告的plugin-33探针复用了恰好 3 条捕获的原 Plugin 主行核对全部行 SHA-256 后用批准的策略生成设置、经原生 Store 往返、再独立于原始行验证。三个有效配置的 SHA-256 均为7cae637b161fc5057487e38b8bc39277b683cb1c3c6b8c366a2a21a97c47616d——与集成测试中source-1001候选把三种配置哈希统一为第一个7cae…的做法完全一致集成测试第 134-141 行。此外全部 275 个此前跟踪的原生文件仍与基线ab1ced72450658ba85399b03293ac37c20278721逐字节一致证明该变更没有引入任何 v3 存储、消息恢复、插件调度或运行时适配改动。集成测试如何执行两种候选与三轮重启集成测试通过环境变量选择候选WKMIGRATE_TEST_PLUGIN_BINARY受审计程序路径、WKMIGRATE_TEST_PLUGIN_BINDING_FIXTURE捕获绑定夹具、WKMIGRATE_TEST_PLUGIN_STATE_ROOT分配配置目录、WKMIGRATE_TEST_PLUGIN_CONFIG_POLICY仅允许空值或source-1001。测试先校验程序字节 SHA-256、父捕获 digest 与 9 行夹具然后执行源目录构建 → 索引校验 → 源选择 → 目标记录转换断言恰好 1 条plugin_binding→ 原生 v3 安装 → 目标验证断言 3 条绑定且CutoverReady false。每轮循环共 3 轮第 3 轮只做历史检查都会停止全部节点 → 以相同配置重建并启动 3 个App→ 等待插件注册pluginhost.Runtime中状态为StatusRunning与集群绑定查询 →在任何新发送之前通过全部 3 个节点逐条核对此前记录的重启前历史reflect.DeepEqual比较完整消息字段→ 再执行新的直接 hook 与普通发送用例。测试明确要求a.onlineDelivery ! nil因为自动 Receive 依赖 product delivery 运行时测试代码第 206 行这正是初跑时零值配置遗漏 Delivery 导致失败的根因。回复断言migrationPluginCommittedReply第 283-303 行检查回复在 10 秒内提交、发送者 UID 等于绑定 UID、负载内容匹配我是名字,收到您的消息hello。source-1001模式下日志记录config_source1001否则记录实际的config_node——每条自动回复的执行器节点因此可审计。2026-09-08 后续历史恢复验收补齐针对重启后只验证新频道新回复的局限2026-09-08-v2-migration-plugin-recovery.md 补齐了单节点与三节点集群各两次完整重启的验收使用原程序字节、原捕获绑定组件、批准的源 1001 统一配置未改变任何 v3 存储或恢复逻辑拓扑自动回复直接 hook 回复重启前历史核对耗时三节点集群1212第一次重启 12 个频道第二次 24 个每个经全部 3 个入口核对33.68 秒单节点集群44第一次重启 4 个频道第二次 8 个22.09 秒两种拓扑合计 32 条插件回复、120 次重启后完整历史读取全部通过整个容器实际运行 56.454 秒。测试不用追加消息预热频道不把最终能读到当作第一份成功结果的完整性。第一次启动受镜像默认 UID 与私有输入文件归属影响失败日志保留纠正仅该临时输入目录的归属后在原隔离限制下重跑通过未改动产品代码。私有证据位于tmp/server-rehearsal-20260908/plugin-recovery-41/。门禁边界这份证据认证了什么又没认证什么原运行时验收证据位于tmp/server-rehearsal-20260907/plugin-32/绑定夹具、测试二进制与源码、两种候选输入、完整运行日志、源码摘录/digest、校验和、最终主机状态。明确未认证cutover_ready仍为 false没有导入、启动、停止或重配置任何源备份或线上目标测试容器已移除。全源插件 prepare、最终可执行文件与配置安装、剩余源业务兼容性缺口、历史恢复、SDK 缓存过渡、100 GiB 性能验收均未认证。配置策略报告同样声明活动插件的程序归档、正式安装及兼容映射尚未接入完整 prepare/import网关与实际业务 SDK、在线客户端、故障切主与生产流量未被覆盖消息格式缺口含 RedDot 与保留的 stream-main 字段、历史会话可见性、独立复现的原生历史恢复问题、SDK 缓存切换与 100 GiB/四小时验收仍是独立未决项。配置夹具是组件/描述符级测试不证明真实活动源插件已通过完整 prepare 门禁plugin_settings验证报告的成功从不设置cutover_ready。这份验收链条的意义在于它把绑定可查询、插件可运行、回复可持久化、重启后历史完整这四个运行时事实与配置策略只影响 config、不碰存储与调度这一变更边界分别钉死在证据上从而为后续把插件 prepare 接入生产迁移工作流提供了可复现的组件级基线——但正式插件兼容检查仍保持关闭。赞分享即时通讯后端【免费下载链接】WuKongIMMore than just IM 不只是即时通讯(IM)项目地址https://gitcode.com/gh_mirrors/wu/WuKongIM点击查看免费下载相关推荐如何在Open Mercato中构建自定义AI AgentAiAgentDefinition实战教程如何在Open Mercato中构建自定义AI AgentAiAgentDefinition实战教程 在 Open Mercato 中构建自定义 AI Age即时通讯后端WuKongIM v2→v3 离线迁移中的插件节点配置分配与原程序隔离验证WuKongIM v2→v3 离线迁移中的插件节点配置分配与原程序隔离验证 导读 本文讲解 WuKongIM 从原版 v2 v2.2.5 20260422 即时通讯后端vm0 Codex app-server集成解析JSON-RPC over stdio的Agent后端vm0 Codex app server集成解析JSON RPC over stdio的Agent后端 vm0okou是一个连接团队现有工具、自主完成跨部即时通讯后端上一篇如何搭建家庭游戏串流服务器Sunshine完整指南下一篇Sunshine游戏串流终极指南免费搭建家庭游戏共享平台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑