Prhub

#47965 [Rust Frontend] Wait for mock engine endpoints before ZMQ connect

原始 PR 作者 reidliu41 合并时间 2026-07-16 17:20 文件变更 1 提交数 3 评论 4 代码增减 +34 / -24

执行摘要

修复 mock engine 启动竞态条件

mock engine 在启动时可能因端点未就绪就执行 ZMQ connect 而触发重试,导致测试耗时增加约 1.4 秒。原 TCP 端点完全无等待逻辑,IPC 端点仅检查 socket 路径是否创建(而非监听器是否就绪),不足以保证连接成功。PR body 明确描述此问题并给出了 before/after 测试结果对比。

精读:此 PR 展示了一个小而精确的竞态修复范例——用原始 TCP/IPC 连接探测替代文件存在性检查,避免 ZMQ 库内部重试延迟。适合作为测试基础设施最佳实践参考。

讨论亮点

BugenZhao 通过 @codex review 触发自动审查,codex 未发现重大 issues。BugenZhao 最终 APPROVED 并表示感谢。

实现拆解

  1. 重构 wait_for_ipc_endpointwait_for_endpoint,统一处理 IPC 和 TCP 端点:
    • 对于 ipc:// 前缀,使用 tokio::net::UnixStream::connect 尝试连接,而非仅检查路径存在。
    • 对于 tcp:// 前缀,新增使用 tokio::net::TcpStream::connect 进行原始 TCP 连接探测。
    • 其他 scheme 保持原有无等待行为。
  2. connect_to_frontend 中,将 wait_for_ipc_endpoint 调用替换为 wait_for_endpoint,同样适用于 handshake 端点和后续 input/output 地址。
  3. 更新 MockEngineConfig::connect_timeout 的 doc comment,语义更精确。
  4. 调整导入:移除 std::path::Path,使用 tokio::time::sleep 替代 tokio::time::timeout(合并导入)。
    变更仅涉及单个源文件 rust/src/engine-core-client/src/mock_engine.rs
文件 模块 状态 重要度
rust/src/engine-core-client/src/mock_engine.rs 引擎客户端 modified 7.9

关键符号

wait_for_endpoint wait_for_ipc_endpoint

关键源码片段

rust/src/engine-core-client/src/mock_engine.rs core-logic

唯一变更文件;重写了端点等待逻辑,新增 TCP 端点支持,替换了 IPC 路径存在性检查为真实连接探测。

/// Wait for an endpoint to accept connections before attempting the ZMQ connect.
async fn wait_for_endpoint(endpoint: &str, connect_timeout: Duration) -> Result<()> {
    // 处理 IPC 端点:尝试连接 UnixStream,而非仅检查路径存在
    if let Some(socket_path) = endpoint.strip_prefix("ipc://") {
        timeout(connect_timeout, async {
            while tokio::net::UnixStream::connect(socket_path).await.is_err() {
                sleep(Duration::from_millis(20)).await;
            }
        })
        .await
        .map_err(|_| Error::HandshakeTimeout {
            stage: "mock engine IPC endpoint",
            timeout: connect_timeout,
        })
    } else if let Some(address) = endpoint.strip_prefix("tcp://") {
        // 新增 TCP 端点支持:尝试原始 TCP 连接直到成功或超时
        timeout(connect_timeout, async {
            while tokio::net::TcpStream::connect(address).await.is_err() {
                sleep(Duration::from_millis(20)).await;
            }
        })
        .await
        .map_err(|_| Error::HandshakeTimeout {
            stage: "mock engine TCP endpoint",
            timeout: connect_timeout,
        })
    } else {
        // 未知 scheme 直接返回,向后兼容
        Ok(())
    }
}// 在 connect_to_frontend 入口处替换调用
// 原:wait_for_ipc_endpoint(engine_handshake, config.connect_timeout).await?;
// 新:
wait_for_endpoint(engine_handshake, config.connect_timeout).await?;// 后续对 input/output 地址的等待也改为 wait_for_endpoint
// 原:wait_for_ipc_endpoint(input_address, config.connect_timeout).await?;
// 新:
wait_for_endpoint(input_address, config.connect_timeout).await?;
wait_for_endpoint(output_addre...

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

低风险:逻辑是等待端点可连接后继续原有 ZMQ connect,未改变连接后的流程。超时机制沿用已有配置(默认 5 秒),不会无限等待。无新增依赖。

影响范围限定于 Rust mock engine 模块的测试和启动流程。所有 mock engine 测试(7 个测试用例)将受益于确定性启动同步,总运行时间从约 1.5 秒降至约 0.03 秒,提升约 50 倍。对生产环境无影响。

测试基础设施变更

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论