麻将节点间路由转发链:失败回退与错误传播语义(ROUTE_SEMANTICS)

麻将节点间路由转发链:失败回退与错误传播语义(ROUTE_SEMANTICS)

第0条(基线)本文件语义以产品源码为权威源;引用只允许以文件与符号(函数、协议名)给出;行号引用前必须复核现码。

第一章 总则

第1条(拓扑与消息链)拓扑为 SCENE(场景服)到 MC(匹配中心)到 GC(游戏中心)到 GS(游戏服)与 PS(玩法服);CLIENT 每玩家一份。消息链:PS 经 CallCenter 到 MC,经转发到 GC,经转发到 GS,经 CallClient 到 CLIENT。

第2条(记法)A --函数--> B 表示 A 调用转发函数将消息送往 B;同进程直调标注 [直调]

第二章 转发链

第3条(状态同步,全量快照)

复制代码
PS Game_BroadcastGameState
  ├─[直调] GameCenter2GameServer_SyncGameState
  └─ module:CallCenter("PlayServer2MatchCenter_SyncGameState", 房间, dwID, GCID, 状态)
      └─ MC 处理器 → Forward_ToGameCenter
          ├─ 同中心:[直调] GC 函数
          └─ 跨中心:CallCenter 到目标中心 → GC 处理器
              └─ Forward_ToGameServer → GS 处理器 → SendToClient → S2C_MAHJONG_SyncGameState

回执:无,单向广播;客户端必须以全量快照为权威状态。

第4条(行动通知)

复制代码
PS 各广播点
  ├─[直调] GameCenter2GameServer_NotifyAction / GameAction
  └─ module:CallCenter("PlayServer2MatchCenter_NotifyAction" / "GameAction", 房间, dwID, GCID, 数据)
      └─ MC 处理器 → Forward_ToGameCenter → GC 处理器 → Forward_ToGameServer → GS → S2C 下发

回执:无显式回执;本家 GameAction 到达时,客户端必须取消对应 C2S 请求的 5 秒超时定时器(BUG#30)。

第5条(回合等待)

复制代码
PS Game_BroadcastRoundWaitState
  ├─[直调] GameCenter2GameServer_RoundWaitState
  └─ module:CallCenter("PlayServer2MatchCenter_RoundWaitState")
      └─ MC 处理器 → GC 处理器 → Forward_ToGameServer → GS 下发

客户端将状态写入并启动定时器;后续全量快照权威覆盖,属预期行为。

第6条(结算:主通道加双兜底)

复制代码
主通道(非外游戏):
PS 结算发布与 Game_End
  └─ module:CallCenter("PlayServer2MatchCenter_EndGame", 房间, 匹配类型, 结算数据)
      └─ MC 处理器 → module:CallSceneServer("MatchCenter2SceneServer_EndGame")   ← 只去场景服,不去 GC
          └─ SCENE 逐玩家 SceneServer2GameCenter_EndGame
              └─ GC Forward_ToGameServer("GameCenter2GameServer_EndGame")
                  └─ GS 处理 → SendToClient("S2C_MAHJONG_EndGame")
兜底通道 A(资金):PS 逐玩家 module_guardians.AutoTakeOut;失败进 5 秒重试队列。
兜底通道 B(送达):场景服结算 pending 重投;转发失败触发。

失败回环:GC 到 GS 转发失败必须回 ForwardFailed 到场景服,由场景服存 pending 或跨中心重路由。EndGame 的客户端通知必须经场景服中转;MC 到场景服一跳无失败检测,任何一跳断裂客户端即收不到 EndGame,只能靠重连拉取。

第7条(崩溃补偿)

复制代码
触发源 A:MC 健康检查或玩家操作发现 PS 断开 → CallSceneServer("MatchCenter2SceneServer_Crash") 并取消房
触发源 B:场景服自发现(验证超时、中心断开处理)→ Center_Call("SceneServer2MatchCenter_Crash")

SCENE MatchCenter2SceneServer_Crash
  └─ 逐玩家 module:CallCenter("SceneServer2GameCenter_Crash", 类型, 参数)
      └─ GC 处理器 → Forward_ToGameServer("GameCenter2GameServer_Crash")
          └─ GS 处理 → 线性流水线回退 → SendToClient("S2C_MAHJONG_Crash")
SCENE 收尾:玩家解绑 → 分享码移除 → 反向索引清理 → 房间移除 → 反向通知 MC 清理

第8条(退款,随崩溃通道)

复制代码
GS 崩溃处理 key 等于期望分支
  └─ RollbackMahjongPendingEntry → RefundFrozenOnAbnormal
      ├─ 状态守卫:无房间且无冻结 → 幂等完成
      ├─ 房间 ID 或冻结 token 校验不符 → 拒绝,不退款
      ├─ token 先推进并持久化
      └─ 发放失败 → token 回退,可重试

另有 Guardians 通道:Mahjong_GuardiansRefundAbnormal

第9条(C2S 请求失败回包级联)

复制代码
PS 处理失败 → module:CallCenter("PlayServer2MatchCenter_RequestFailed")
  └─ MC 处理器 → Forward_ToGameCenter → GC 处理器 → Forward_ToGameServer
      └─ GS 处理器:协议映射表 → SendToClient(对应 S2C, 错误码);入场失败回滚;退房失败清陈旧房号
MC 前置错误(转发前):GetPlayableRoomOrReply
  ├─ 房间不存在 → 回 3300001
  └─ PS 断开 → 回 3300017 并触发断开处理

第10条(跨中心重路由)

复制代码
SCENE ForwardFailed 处理
  ├─ 成功匹配 → 回应答,避免开局等待
  ├─ EndGame → 存 pending
  ├─ 玩家在当前中心 → 跨中心转发(带元数据)
  ├─ 否则转原始中心
  └─ 无可用中心 → 回 RequestFailed 3300017
GC 跨中心转发失败 → 回补 RequestFailed 到源 GC;本地兜底失败仅日志

第三章 失败模式

第11条(失败模式清单)

# 失败点 检测 回退 客户端感知
F1 PS 到 MC 转发(异步无失败回调) 无检测;MC 注释确认无可靠回调 健康检查每 16 帧回收僵尸房间 无消息;请求 5 秒超时;推送静默丢失
F2 MC 到 GC 转发失败 MC 侧转发返回失败 仅记错误日志;调用方忽略返回值 消息静默丢失
F3 GC 到 GS 转发失败 GC 侧转发返回失败 回 ForwardFailed;跨中心重试或回错误码 回补成功时收到错误码,否则静默
F4 PS 断线且玩家操作途中 MC 连接校验 回 3300017 并通知场景服崩溃、取消房 先收错误码,后收崩溃通知
F5 PS 静默断线 MC 健康检查 逐房通知场景服崩溃并取消房 崩溃通知
F6 场景服到 GC 崩溃通知失败 可用性过滤;调用返回失败 空房通知重试一次;崩溃通知不重试 不可达时冻结悬挂,等重连或重投
F7 GS 退款失败 退款返回失败 不确认;场景服持续重投至上限暂停,重连再触发,总上限外永久放弃 收不到回退确认;pending 保留供拉取
F8 结算送达失败 场景服转发失败回调 存 pending 定时重投;资金另有自动结算兜底 正常收 EndGame;失败时无感知,重连恢复
F9 崩溃结算 key 乱序 GS 线性流水线比较 小于期望跳过并确认;大于期望只确认等待;等于执行回退 均收崩溃通知;大于期望不回退
F10 客户端请求超时 请求定时器 回调 3300101 并发布错误事件;房间变更释放锁;断线退出全量取消 提示操作失败
F11 跨中心 GC 不可达 连接检查与转发 带元数据时回补 RequestFailed;本地兜底失败仅日志 回补成功收错误码,否则静默
F12 场景服自发现 PS 断开 验证定时器 升级为类型 6 崩溃 崩溃通知
F13 无可用中心建房 选服返回空 建房回 3300004 场景服映射崩溃类型并补偿
F14 EndGame 房间索引缺失 房间查询为空 仅记日志返回,不回退不补偿 资金靠自动结算;无 S2C
F15 退房无场景服 场景服 ID 不大于 0 回 3300001 退房错误码

第四章 重复与乱序防护

第12条(防护清单)

机制 位置 说明
结算去重(客户端) mahjong_client_core.lua 相同房间已有结算结果且待显示时跳过重复 EndGame
陈旧房间守卫 同上 EndGame 先查房间归属;崩溃通知无此守卫 SUSPECT-2
座位号回归拒绝 同上 过期快照座位号倒退必须恢复旧值
倒计时单调递减 同上 换三张与定缺阶段拒绝倒计时回升
定时器锚定策略 同上 进行中与等待响应不重启定时器;换三张与定缺每次重启收敛
全局倒计时锚点 同上 仅广播非零值建立
请求超时取消 同上 本家行动到达取消对应请求超时定时器(BUG#30)
PK 审计 同上 仅无选项的他人通知才清本家 pending
定缺幂等 mahjong_play_server.lua 已提交直接返回
建房幂等 mahjong_match_center.lua 已有活跃玩法服则忽略;等待装载则复用转发
崩溃验证去重 mahjong_scene.lua 验证中标志加冷却,防重复验证
崩溃 key 乱序 mahjong_game_server.lua 线性流水线:小于跳过、大于等待、等于执行
结算重投去重 mahjong_scene.lua 确认后删除 pending;重投更新下次重试时间
请求回调单槽 mahjong_client_core.lua 同协议新请求先关旧定时器与旧回调

第五章 模拟注入点

第13条(注入点)

注入场景 mock 位置 注入方式
PS 到客户端直达转发 node_ps.lua 转发覆盖 拦截各 PS 侧协议直接投递客户端;延迟参数即乱序注入点
PS 节点接收 MC 协议 node_ps.lua 协议注册 解包后调真实全局函数;注入失败即替换为丢弃桩或抛错
S2C 路由表 node_ps.lua 初始化 路由项含延迟字段,即乱序注入点
玩家过滤 node_ps.lua 投递覆盖 按 dwID 过滤;改条件可模拟目标玩家不在本机
通用网络层 framework.lua 转发 stub 全部经路由表与消息总线;无路由条目即静默丢弃
客户端节点 node_client.lua 客户端处理器自动收集,可断言收到与未收到
转发失败 framework.lua 清空路由条目或包装投递为丢弃
中心断开 mahjong_match_center.lua stub 连接查询返回空,使转发返回失败
结算重投 mahjong_scene.lua 重试节流 直接调用并推进下次重试时间;断言投递计数
GS 不可达 mahjong_game_center.lua 转发 玩家查询返回空且非远程,使转发返回失败

模拟局限:node_ps.lua 只仿真 PS 到客户端直达,未仿真 MC、GC、GS 中间节点;其余 PS 侧协议落入仅日志分支。场景服、GC、GS 链必须按 loader.lua 的导出方式另行装载模块后手工接线。

第六章 缺陷与缺口

第14条(SUSPECT 清单)

  1. SUSPECT-1(mock 缺陷)node_ps.lua EndGame 广播取第 4 个参数(匹配类型)而非第 5 个(结算数据),客户端收到非表数据即丢弃,mock 下结算显示永不触发;测试套件必须先修此点或直接断言该缺陷。
  2. SUSPECT-2 崩溃通知无陈旧房间守卫、无去重:玩家进新房后旧房崩溃会误触发事件。
  3. SUSPECT-3 MC 四个 S2C 转发处理器忽略转发返回值:GC 断开时消息静默丢失且无补偿(F2)。
  4. SUSPECT-4 EndGame 主通道依赖 MC 到场景服一跳且无失败检测:客户端通知无兜底,只能重连拉取(F8)。
  5. SUSPECT-5 GS 崩溃未来 key 分支确认后不回退且无重试:退款可能被永久跳过。
  6. SUSPECT-6 结算投递目标中心无效即永久放弃:资金只能靠自动结算通道,若 PS 已死则悬挂。
  7. SUSPECT-7 空房关闭通知只重试一次:二次失败后冻结悬挂,无主动补偿。
  8. SUSPECT-8 客户端 EndGame 去重窗口仅覆盖待显示期间:显示消费后重投的 EndGame 会重复展示结算。
  9. SUSPECT-9 MC 建房先写索引后调用:PS 未收到请求时房间成为僵尸,回收依赖健康检查,窗口期玩家已分配无游戏。
  10. SUSPECT-10 请求回调每协议单槽:同协议并发请求后发覆盖先发,覆盖场景语义由业务层承担。

第七章 测试点

第15条(测试点清单,共 32 项)

  1. 正向 状态广播后客户端收到全量快照且含私有手牌。
  2. 正向 行动通知逐玩家送达:动作玩家带完整手牌,旁观带手牌数。
  3. 正向 本家行动到达后请求超时定时器被取消,无超时事件。
  4. F2 注入中心断开:转发返回失败、状态同步静默丢弃、无错误回包。
  5. F1 清空 PS 到 MC 路由:客户端无消息;请求 5 秒后回调超时并发布错误事件。
  6. F4 PS 断开且玩家操作:回 3300017 且触发崩溃通知与取消房。
  7. F4 错误码到达 GS:下发带错误码的 S2C。
  8. F5 健康检查发现断开:该服所有房间触发场景服崩溃与索引清理。
  9. F13 无可用玩法服建房:回 3300004。
  10. 幂等 取消房对不存在房间二次调用安全返回。
  11. 幂等 建房同房重复且游戏进行中:忽略。
  12. F12 崩溃处理器收到不匹配 PS ID:发起验证,超时后升级类型 6。
  13. F6 崩溃逐玩家通知且场景服 ID 被补全。
  14. F7 退款失败:不确认,pending 计数递增并重投。
  15. F9 key 小于期望:只确认并通知,不退款。
  16. F9 key 大于期望:只确认,不回退(SUSPECT-5)。
  17. 退款 房号不匹配:拒绝且零发放。
  18. 退款 冻结 token 不匹配:拒绝。
  19. 退款 发放失败:token 回退可重试。
  20. F8 转发失败:pending 建立,到期重发结算。
  21. F8 目标中心不可达:重试计数递增,不得每帧无限重试。
  22. F8 重试达上限:暂停;重连重新触发。
  23. F8 总重试超上限:pending 永久放弃并清理。
  24. F3 转发失败且成功匹配:回应答,游戏不被卡住。
  25. F3 转发失败跨中心重路由:带元数据转发。
  26. F3 无可用中心:回 3300017。
  27. F11 跨中心转发失败且带元数据:源中心收到回补。
  28. F10 请求超时且房间已变更:仍回调超时并发布错误事件。
  29. 去重 结算未显示期间重复到达:跳过;结算失败码触发错误事件。
  30. 乱序 倒计时增大与座位号倒退均被拒绝。
  31. SUSPECT-1 mock 结算广播投递匹配类型:断言客户端丢弃;先修后测。
  32. 重试 准备请求本地状态未就绪:200 毫秒后自动重试一次。
相关推荐
本人手速666+1 小时前
企微自动回复系统如何通过 WeComApi 从关键词升级为业务流程
自动化·企业微信·企微外部群开发·wecomapi·企业微信二次开发
机核研创社1 小时前
一条橡筋的接口,决定内裤睡裤的舒适度——全自动双头接橡筋机怎么做明橡筋?
人工智能·自动化
kali-Myon1 小时前
分享一个网络安全 AI 工具导航项目 SecSkills
安全·ai·github·ctf
wechatbot8882 小时前
【极客互动】企业微信Spring Boot 调度 SearchContact开发自动添加外部联系人网关
汇编·微信·自动化·企业微信·rpa
liulilittle2 小时前
mock 框架架构
ai·架构·自动化·llm·mock·测试·tools
liulilittle2 小时前
C++ 引擎接口到 mock 的映射(INTERFACE_MAP)
ai·自动化·llm·mock·lua·测试·tools
apple_692658853 小时前
DLSS5画质增强 mayflyMods v1.2.5 四合一工具:DLSS5画质增强 + MFG多帧生成 + 游戏库启动 + MOD模组管理
ai·dlss5