Prhub

#37182 [CI] Fix unreachable FakeReq field initialization

原始 PR 作者 alphabetc1 合并时间 2026-08-31 11:51 文件变更 1 提交数 1 评论 3 代码增减 +24 / -4

执行摘要

修复 FakeReq 不可达初始化并补 Mamba 状态回归测试

PR body 明确指出:#37108 inserted detach_kv() before the remaining _FakeReq field initialization. This left those assignments after return kv, so tests that call SessionSlot.save_from_req() fail with AttributeError: _FakeReq has no attribute mamba_next_track_idx. This was exposed by #34565. 核心诉求是修复测试辅助类中不可达初始化导致的回归,让 mem_cache / streaming session 单测恢复稳定,并对 Mamba 状态在会话插槽中的保存恢复提供回归保护。

值得快速浏览(无需精读)。该 PR 本身改动很小,但有两个可借鉴点:

  1. 遇到"测试突然 AttributeError"时,先检查是否有字段赋值被误放在 return 之后的不可达位置,这比盲目补字段更能定位根因;
  2. save_from_req → restore_to_req 往返断言是一种低成本、高价值的会话状态回归测试范式。

若要进一步加固,可考虑把新回归测试的断言扩展至全部会话状态字段,并在 review 检查单中增加"return 后不可达代码"的排查项。

讨论亮点

该 PR 没有人工 review 评论,可用信息来自 PR 评论与自动审查:

  • Codex 自动审查在 commit 77bf5f6 上完成 Code Review,状态 Completed,无 findings(👍),说明修改本身未引入新的可报告问题。
  • 作者主动 /rerun-test test_streaming_session_unit.py,GitHub Actions 返回 ✅(ubuntu-latest,1 个测试通过),验证修复有效。
  • 值得注意:PR body 对回归来源的定位非常明确(#37108return kv 后留代码、#34565 暴露),但仓库没有就"如何系统性地避免同类不可达代码"展开人工讨论,这一点在 review 流程上仍有改进空间。

实现拆解

本次变更全部落在 test/registered/unit/mem_cache/test_streaming_session_unit.py,共四步:

  1. 字段初始化移回 __init__:把 mamba_next_track_idxmamba_last_track_seqlenmamba_branching_seqlento_finishfinished_reasonfinished_len 六个赋值从 detach_kv()return 之后搬到 _FakeReq.__init__ 末尾,并新增 mamba_last_track_idx = NoneSessionSlot 需要该字段)。这样即使测试从未调用过 detach_kv()save_from_req() 也能读取到完整字段。
  2. 精简 detach_kv():方法体收窄为仅执行 kv, self.kv = self.kv, ReqKvInfo()return kv,与之前语义保持一致。
  3. 新增往返回归测试test_session_slot_round_trip_preserves_mamba_state() 构造带四个 Mamba 追踪字段的 _FakeReq,依次调用 save_from_req(req, is_first=True)restore_to_req(next_req),最后逐一断言四个字段数值完整保留,防止后续改动再次丢失初始化。
  4. 验证与 CI:本地环境无 pytest,作者仅运行 pre-commit;通过 /rerun-test test_streaming_session_unit.py 在 ubuntu-latest 上定向执行该文件,1 个测试通过。

涉及文件与符号:test/registered/unit/mem_cache/test_streaming_session_unit.py_FakeReq.__init__detach_kvtest_session_slot_round_trip_preserves_mamba_state);无配置、schema 或部署配套改动。

文件 模块 状态 重要度
test/registered/unit/mem_cache/test_streaming_session_unit.py 流式会话 modified 5.23

关键符号

_FakeReq.__init__ detach_kv test_session_slot_round_trip_preserves_mamba_state

关键源码片段

test/registered/unit/mem_cache/test_streaming_session_unit.py test-coverage

唯一变更文件。修复 _FakeReq 中因 detach_kv() 的 return 而不可达的字段初始化,补上 SessionSlot 需要的 mamba_last_track_idx,并新增 Mamba 状态往返回归测试,是本次回归修复与测试守护的载体。

class _FakeReq:
    """测试用最小请求对象,字段与真实 Req 对齐,供 SessionSlot 往返读写。"""
​
    def __init__(
        self, session_id: str, req_pool_idx: int, committed: int, allocated: int
    ):
        # 会话与 KV 信息:save_from_req / restore_to_req 主要通过这些字段工作
        self.session = SimpleNamespace(
            session_id=session_id,
            streaming=True,
            finish_req=lambda req: None,
            abort_req=lambda: None,
            _inflight=False,
        )
        self.kv = ReqKvInfo(
            req_pool_idx=req_pool_idx,
            kv_committed_len=committed,
            kv_allocated_len=allocated,
            swa_evicted_seqlen=0,
            cache_protected_len=0,
        )
        # 以下字段原本被误放在 detach_kv() 的 return 之后(不可达代码),
        # 导致 save_from_req() 读取 mamba_next_track_idx 时报 AttributeError;
        # 本 PR 将全部初始化移回 __init__,并补上 SessionSlot 需要的 mamba_last_track_idx
        self.origin_input_ids = list(range(committed))
        self.output_ids = []
        self.extra_key = None
        self.cache_salt = None
        self.last_node = None
        self.swa_uuid_for_lock = None
        self.skip_lock_node_ids = {}
        self.mamba_pool_idx = None
        self.mamba_ping_pong_track_buffer = None
        self.mamba_next_track_idx = None
        self.mamba_last_track_idx = None
        self.mamba_last_track_seqlen = None
        self.mamba_branching_seqlen = None
        self.to_finish = None
        self.finished_reason = None
        self.finished_len = None
​
    def detach_kv(self):
        """剥离本轮 KV,把新的空 ReqKvInfo 放回请求,供后续写入复用。"""
        kv, self.kv = self.kv, ReqKvInfo()
        return kv
​
​
def test_session_slot_round_trip_preserves_mamba_state():
    """回归测试:SessionSlot 保存 / 恢复请求时必须完整保留 Mamba 追踪状态。"""
    req = _FakeReq("session-a", req_pool_idx=0, committed=4, allocated=4)
    req.mamba_next_track_idx = 1
    req.mamba_last_track_idx = 0
    req.mamba_last_track_seqlen = 3
    req.mamba_branching_seqlen = 2
​
    slot = SessionSlot()
    slot.save_from_req(req, is_first=True)
​
    next_req = _FakeReq("session-a", req_pool_idx=1, committed=0, allocated=0)
    slot.restore_to_req(next_req)
​
    # 恢复后的请求应保留全部 Mamba 追踪状态,否则流式会话续跑时状态错乱
    assert next_req.mamba_next_track_idx == 1
    assert next_req.mamba_last_track_idx == 0
    assert next_req.mamba_last_track_seqlen == 3
    assert next_req.mamba_branching_seqlen == 2

评论区精华

Codex 自动审查结果 other

Codex 在 commit 77bf5f6 上完成代码审查,状态 Completed,未报告代码问题。

结论:自动审查通过,无遗留问题。 · 已解决

定向重跑受影响的单元测试 测试

作者通过 /rerun-test test_streaming_session_unit.py 触发定向 CI,验证修复后的测试文件。

结论:ubuntu-latest 上 1 个测试通过,修复有效。 · 已解决

风险与影响

  1. 回归风险极低:变更只落在单测文件中的 fake 类与新增测试,不触碰生产代码路径。
  2. 覆盖有限:新测试只断言 Mamba 追踪四个字段;to_finishfinished_reasonfinished_len 等同样被移回初始化的字段没有独立的往返断言,SessionSlot 未来扩展字段时仍可能重演同类遗漏。
  3. 根因模式未在源码侧排查#37108 的错误是"在 return 之后写赋值语句",这种不可达代码模式不一定只存在于测试文件,生产代码中若有类似情况不会被本次测试覆盖。
  4. 迭代依赖 CI:本地缺少 pytest 环境,意味着对单测文件的快速迭代仍需借助 GitHub Actions 验证。

受影响范围

  • 恢复因 AttributeError 崩溃的 mem_cache / streaming session 单测,解除对 #34565 等后续 PR 的 CI 阻塞;
  • 为 streaming session 的 Mamba 状态保存与恢复提供回归守护,降低 mem_cache 重构期(如 #37164)的状态丢失风险;
  • 对推理服务、最终用户、API 无任何影响,因为所有变更都在 test/ 目录内。

影响程度:低。属于测试基础设施层面的定向修复。

纯测试文件变更 测试回归修复 覆盖有限 根因模式未排查

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论