# PR #45489 完整报告

- 仓库：`vllm-project/vllm`
- 标题：[CI] Wait for SSL cert refresher events in the test
- 合并时间：2026-06-13 12:57
- 原文链接：http://prhub.com.cn/vllm-project/vllm/pull/45489

---

# 执行摘要

- 一句话：修复 SSL 证书刷新测试的时序竞态
- 推荐动作：建议合入，消除 CI 不稳定因素。可关注后续是否有同类竞态模式出现在其他测试中。

# 功能与动机

修复 AMD API Server 集成测试中偶发失败的时序问题：测试在 `touch` 文件后固定等待 1 秒，但在 CI 繁忙时异步文件监视器的回调可能延迟，导致断言失败。PR body 指出 "If CI scheduling delays the callback slightly, the same test fails even though the production watcher still works."

# 实现拆解

1. 新增辅助函数 `wait_for_counts`：轮询直到 `load_cert_chain_count` 和 `load_ca_count` 达到预期值，超时后断言失败。
2. 将原 `test_ssl_refresher` 中的 `await asyncio.sleep(1)` 替换为 `await wait_for_counts(...)` 调用。
3. 在 `stop()` 后添加 `await asyncio.sleep(0)` 确保停止事件完成，并记录停止时的计数，然后再次 touch 文件并验证计数不变。

关键文件：
- `tests/entrypoints/serve/utils/test_ssl_cert_refresher.py`（模块 测试；类别 test；类型 test-coverage；符号 wait_for_counts）: 唯一变更文件，引入等待函数替代固定睡眠。

关键符号：wait_for_counts

## 关键源码片段

### `tests/entrypoints/serve/utils/test_ssl_cert_refresher.py`

唯一变更文件，引入等待函数替代固定睡眠。

```python
async def wait_for_counts(
    ssl_context: MockSSLContext,
    *,
    cert_chain_count: int,
    ca_count: int,
    timeout: float = 5.0,
) -> None:
    """轮询等待直到计数达到或超过预期值，避免固定 sleep 的竞态。"""
    deadline = asyncio.get_running_loop().time() + timeout
    while True:
        if (
            ssl_context.load_cert_chain_count >= cert_chain_count
            and ssl_context.load_ca_count >= ca_count
        ):
            return  # 条件满足，提前返回

        if asyncio.get_running_loop().time() >= deadline:
            # 超时则断言，确保测试快速失败
            assert ssl_context.load_cert_chain_count >= cert_chain_count
            assert ssl_context.load_ca_count >= ca_count

        await asyncio.sleep(0.05)

```

# 评论区精华

无 review 评论。

- 暂无高价值评论线程

# 风险与影响

- 风险：风险极低，仅修改测试逻辑。轮询超时 5 秒可能会轻微增加测试失败时的时间，但原测试在失败时同样会超时。超时后的断言仍能保证正确性。
- 影响：影响范围限于 `test_ssl_cert_refresher.py`，消除 AMD CI 中的假阳性失败。对其他模块无影响。
- 风险标记：暂无

# 关联脉络

- 暂无明显关联 PR