# PR #25725 完整报告

- 仓库：`sgl-project/sglang`
- 标题：Fix the misnamed request finish-check method to reflect its mutating semantics
- 合并时间：2026-05-19 09:22
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/25725

---

# 执行摘要

- 一句话：重命名 check_finished 为 update_finish_state 以澄清语义
- 推荐动作：推荐开发者在类似场景中遵循命名约定：对副作用的修改操作使用动词（update/set/reset），对只读查询使用谓词（is_/has_/finished）。该 PR 虽小但体现了代码清晰度的重要性。

# 功能与动机

方法原名 check_finished 从命名上看像是只读谓词，但实际上它具有 state-advancing 副作用：会修改 finished_reason、finished_len、to_finish 等字段，甚至通过 _check_vocab_boundary_finish 覆盖 output_ids。返回值为 None，真正的完成状态需要后续通过 req.finished() 方法获取。同名的 finished() 方法已经是真正的谓词，导致同一词根但语义相反的命名冲突。因此重命名为 update_finish_state，使动词 'update' 和名词 'state' 都明确表达该方法的变更语义。

# 实现拆解

1. **方法定义重命名**：在 python/sglang/srt/managers/schedule_batch.py 的 Req 类中，将 `check_finished` 方法定义重命名为 `update_finish_state`，签名保持不变（`new_accepted_len: int = 1`）。

2. **批处理处理器调用点更新**：在 python/sglang/srt/managers/scheduler_components/batch_result_processor.py 的四处位置（`process_batch_result_prebuilt`、`process_batch_result_prefill` 两处、`process_batch_result_decode`）将 `req.check_finished(...)` 替换为 `req.update_finish_state(...)`，同时更新了相关的注释文字。

3. **DLLM 调度器调用点更新**：在 python/sglang/srt/dllm/mixin/scheduler.py 的 `process_batch_result_dllm` 中替换调用。

4. **投机解码验证阶段更新**：在 python/sglang/srt/speculative/eagle_info.py（两处）、dflash_info.py 和 ngram_info.py 中替换调用。

5. **注释更新**：在 python/sglang/srt/disaggregation/decode_schedule_batch_mixin.py 和 python/sglang/srt/managers/schedule_policy.py 中更新了描述性注释，将 `check_finished` 替换为 `update_finish_state`。

6. **无测试变更**：所有改动均为纯文本替换，不涉及行为变化，因此未修改测试文件。

关键文件：
- `python/sglang/srt/managers/schedule_batch.py`（模块 调度器；类别 source；类型 core-logic；符号 check_finished, update_finish_state）: 重命名核心方法定义，是所有调用的源头。
- `python/sglang/srt/managers/scheduler_components/batch_result_processor.py`（模块 调度器；类别 source；类型 core-logic）: 最主要的调用者，包含四处调用点和多处注释更新。
- `python/sglang/srt/dllm/mixin/scheduler.py`（模块 DLLM 调度；类别 source；类型 core-logic）: DLLM 调度后处理方法中的调用点。
- `python/sglang/srt/speculative/eagle_info.py`（模块 投机解码；类别 source；类型 core-logic）: 投机解码验证阶段中的调用点，涉及两处调用。

关键符号：update_finish_state

## 关键源码片段

### `python/sglang/srt/managers/schedule_batch.py`

重命名核心方法定义，是所有调用的源头。

```python
def update_finish_state(self, new_accepted_len: int = 1):
    """
    更新请求的完成状态，而非仅仅检查。
    这是对原 check_finished 的重命名，以反映其修改语义。
    """
    # 如果已经完成则直接返回
    if self.finished():
        return

    # 处理通过 to_finish 提前设置的终止原因
    if self.to_finish:
        self.finished_reason = self.to_finish
        self.to_finish = None
        return

    # 检查是否达到最大新 token 数
    if len(self.output_ids) >= self.sampling_params.max_new_tokens:
        self.finished_reason = FINISH_LENGTH(
            length=self.sampling_params.max_new_tokens
        )
        self.finished_len = self.sampling_params.max_new_tokens
        return

    # 检查 grammar 是否终止
    if self.grammar is not None:
        if self.grammar.is_terminated():
            self.finished_reason = FINISH_MATCHED_TOKEN(matched=self.output_ids[-1])
            return

    new_accepted_tokens = self.output_ids[-new_accepted_len:]

    # 依次检查多种终止条件
    if self._check_token_based_finish(new_accepted_tokens):
        return
    if self._check_vocab_boundary_finish(new_accepted_tokens):
        return
    if self._check_str_based_finish():
        return

```

### `python/sglang/srt/managers/scheduler_components/batch_result_processor.py`

最主要的调用者，包含四处调用点和多处注释更新。

```python
# process_batch_result_prebuilt 中的调用示例
for req in batch.reqs:
    req.time_stats.set_decode_prebuilt_finish_time()
    # 原为 req.check_finished()，重命名以反映其修改完成状态的语义
    req.update_finish_state()
    if req.finished():
        req.time_stats.set_quick_finish_time()
        if self.server_args.enable_hisparse:
            self.hisparse_coordinator.request_finished(req)
        release_kv_cache(req, self.tree_cache)

# process_batch_result_prefill 中的调用示例
for i, (req, next_token_id) in enumerate(zip(batch.reqs, next_token_ids)):
    if req.finished() or req.is_retracted:
        continue
    if req.inflight_middle_chunks <= 0:
        req.time_stats.set_prefill_finished_time()
        req.output_ids.append(next_token_id)
        self._maybe_update_reasoning_tokens(req, next_token_id)
        # 原为 req.check_finished()
        req.update_finish_state()
        if req.finished():
            self._maybe_collect_routed_experts(req)
            self._maybe_collect_indexer_topk(req)
            release_kv_cache(req, self.tree_cache)
            req.time_stats.set_completion_time()
        elif not batch.decoding_reqs or req not in batch.decoding_reqs:
            maybe_cache_unfinished_req(req, self.tree_cache)

```

# 评论区精华

该 PR 没有引发讨论，变更直观且机械。

- 暂无高价值评论线程

# 风险与影响

- 风险：风险极低：所有改动均为纯机械重命名，不涉及逻辑变更。但需确认没有遗漏调用站点；由于改动文件覆盖了主要调度路径和投机解码路径，遗漏可能性较小。如果有外部代码依赖原始方法名（如自定义插件或 fork），可能会中断，但仓库内部已完全覆盖。
- 影响：对用户无影响。对开发者提升了代码可读性，消除了命名歧义，降低了将变体方法误当作谓词使用的风险。未来维护者能更直观地理解该方法会修改状态。
- 风险标记：低风险 , 纯重命名

# 关联脉络

- PR #25728 Pull the max-prefix-len computation into its own helper and rename the matched-token argument: 同属调度器重构系列，修改了相同的 schedule_batch.py 文件
- PR #25726 Confine req-pool-idx assignment to the pool allocator: 同属重构系列，也涉及 schedule_batch.py 的简化