From 928acb430220e9d0e47b470372aad3509c3d6229 Mon Sep 17 00:00:00 2001 From: kdletters Date: Mon, 11 May 2026 17:24:24 +0800 Subject: [PATCH] Extend sccache startup timeout for Windows builds --- .hermes/shared-memory/pitfalls.md | 8 +-- ...EDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md | 71 +++++++++++++++++-- 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/.hermes/shared-memory/pitfalls.md b/.hermes/shared-memory/pitfalls.md index 7d9c6345..f3a582f1 100644 --- a/.hermes/shared-memory/pitfalls.md +++ b/.hermes/shared-memory/pitfalls.md @@ -383,10 +383,10 @@ ## Rust 构建不要让不可用的 sccache 阻断 rustc -- 现象:Cargo 报 `could not execute process sccache ... rustc.exe -vV (never executed)`,或 `sccache: caused by: Failed to send data to or receive data from server / Failed to read response header / failed to fill whole buffer`;真实 `rustc -Vv` 可以执行,但构建在调用包装器时失败。 -- 原因:环境、Jenkinsfile 或 `server-rs/.cargo/config.toml` 启用了 `sccache` wrapper,但当前 agent 没有可执行的 `sccache`、PATH 中 shim 损坏,或本地 sccache server/client 通道状态损坏。 -- 处理:本地临时排障可在 Git Bash 中执行 `RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo build ...`;`npm run dev:rust` 的 SpacetimeDB publish 已在命中 sccache 通信失败时自动清空 wrapper 重试一次;生产流水线必须先实际执行 `sccache --version`,失败时移除 `RUSTC_WRAPPER` 并回退到直接 `rustc`。 -- 验证:`rustc -Vv` 能输出版本;清空 wrapper 后 `cargo check --target=wasm32-unknown-unknown --release` 能通过;Jenkins 日志出现“未找到可用 sccache,改用 rustc 直接构建”后仍继续真实构建。 +- 现象:Cargo 报 `could not execute process sccache ... rustc.exe -vV (never executed)`、`sccache: error: Timed out waiting for server startup`,或 `sccache: caused by: Failed to send data to or receive data from server / Failed to read response header / failed to fill whole buffer`;真实 `rustc -Vv` 可以执行,但构建在调用包装器时失败。 +- 原因:环境、Jenkinsfile 或 `server-rs/.cargo/config.toml` 启用了 `sccache` wrapper,但当前 agent 没有可执行的 `sccache`、PATH 中 shim 损坏,或本地 sccache server/client 通道状态损坏。Windows 本机若配置了 `SCCACHE_OSS_*`,sccache daemon 冷启动会先经 OSS/本机代理完成缓存读写检查,再监听 `127.0.0.1:4226`;代理或 OSS 链路慢时,Cargo 的 `sccache rustc -vV` 可能先超时。 +- 处理:保留 `server-rs/.cargo/config.toml` 的 `rustc-wrapper = "sccache"`;Windows 本机优先在 `%APPDATA%\Mozilla\sccache\config\config` 写入 `server_startup_timeout_ms = 60000`,拉长 client 等待 daemon 完成 OSS 初始化的时间,然后删除 `server-rs/target/.rustc_info.json` 里缓存的失败探测结果并重跑原始 Cargo 命令。冷启动验证优先用 `sccache --stop-server`,不要在另一个 `cargo` / `rustc` 仍在编译时 `taskkill /F /IM sccache.exe /T`,否则 proc-macro crate 可能被打断并表现为 `serde_derive` / `spacetimedb-bindings-macro` 的 `sccache ... exit code: 1`。若只做临时排障,可在 Git Bash 中执行 `RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo build ...`,或在 PowerShell 用 `cargo check -p api-server --config "build.rustc-wrapper=''"` 一次性绕过 wrapper;生产流水线必须先实际执行 `sccache --version`,失败时移除 `RUSTC_WRAPPER` 并回退到直接 `rustc`。 +- 验证:`rustc -Vv` 能输出版本;冷启动后原始 `cargo check -p api-server` 和 `cargo check -p spacetime-module` 能通过;`sccache --show-stats` 显示 `Cache location oss, name: genarrative-sccache`,证明仍在使用 sccache/OSS 缓存;Jenkins 日志出现“未找到可用 sccache,改用 rustc 直接构建”后仍继续真实构建。 - 关联:`scripts/dev-rust-stack.sh`、`jenkins/Jenkinsfile.production-stdb-module-build`、`docs/technical/SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md`、`docs/technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md`。 ## 生产发布入口不要沿用旧 Jenkinsfile / 一体化脚本 diff --git a/docs/technical/SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md b/docs/technical/SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md index 3340dbdb..6eb83f67 100644 --- a/docs/technical/SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md +++ b/docs/technical/SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md @@ -7,6 +7,7 @@ Windows 本地执行 `npm run dev:rust` 或 `spacetime publish` 时,`spacetime 当本机 sccache server 状态损坏、client/server 通信异常或版本残留不一致时,可能出现: ```text +sccache: error: Timed out waiting for server startup. Maybe the remote service is unreachable? sccache: error: failed to execute compile sccache: caused by: Failed to send data to or receive data from server sccache: caused by: Failed to read response header @@ -15,9 +16,24 @@ sccache: caused by: failed to fill whole buffer 这类错误发生在 rustc wrapper 层,不能说明 SpacetimeDB module 代码本身编译失败。 +## 2026-05-11 本机根因定位 + +本机 `cargo check -p api-server` 失败时,Cargo 还没有进入业务 crate 编译,而是在读取 `server-rs/.cargo/config.toml` 后执行 `sccache rustc -vV` 探测编译器版本。失败的 stderr 会被写入 `server-rs/target/.rustc_info.json`,内容为 `Timed out waiting for server startup`。 + +当前 PowerShell 环境设置了 `SCCACHE_OSS_BUCKET=genarrative-sccache`、`SCCACHE_OSS_ENDPOINT=https://oss-rg-china-mainland.aliyuncs.com` 和 `SCCACHE_OSS_KEY_PREFIX=genarrative`,且没有设置本地 `SCCACHE_DIR`。因此 sccache daemon 冷启动时会先初始化 OSS 远端缓存,并执行 `.sccache_check` 的读写检查;日志中可见 `Init oss cache ...`、`proxy(http://127.0.0.1:7897/) intercepts ...`,随后才出现 `server started, listening on 127.0.0.1:4226`。 + +本次排查的结论是:冷启动失败主要发生在 sccache client 等待 daemon 启动的握手窗口内,而 daemon 启动又依赖 OSS/本机代理链路先完成缓存可读写检查。代理或 OSS 链路稍慢时,Cargo 调用的 `sccache rustc -vV` 会先超时;daemon 预热后直接执行同一条 `sccache rustc -vV` 又可能成功,所以这是冷启动/通道状态问题,不是 `api-server` 或 Rust 代码错误。 + +辅助证据: + +1. `rustc -vV` 可直接输出版本,说明 Rust 工具链本身可用。 +2. `tasklist` 曾只看到 `sccache --show-stats` 客户端进程,`netstat` 只出现到 `127.0.0.1:4226` 的 `SYN_SENT`,没有真正的 `LISTEN`,说明当时 client 正在等一个尚未成功监听的 daemon。 +3. 在子进程中临时清掉 `SCCACHE_OSS_*` 并设置本地 `SCCACHE_DIR` 后,sccache 退回本地磁盘缓存,日志显示 `Init disk cache ...`,`rustc -vV` 和 `sccache --show-stats` 均能完成。 +4. `C:\Users\DSK\AppData\Roaming\Mozilla\sccache\config\config` 缺失只是非致命 warning,本机实际配置来自环境变量。 + ## 本地开发处理 -`scripts/dev-rust-stack.sh` 的 publish 阶段继续由 SpacetimeDB CLI 内部调用 Cargo,并通过 `--build-options="--debug"` 使用 debug 构建参数。遇到 sccache 通信或 wrapper 失败时,本地排障仍优先绕过 wrapper 验证 rustc 本身可用。 +`scripts/dev-rust-stack.sh` 的 publish 阶段继续由 SpacetimeDB CLI 内部调用 Cargo,并通过 `--build-options="--debug"` 使用 debug 构建参数。遇到 sccache 冷启动超时时,优先保留 `sccache` wrapper,并修复 sccache daemon 的启动等待时间;只有在排除 sccache 本身问题时,才临时绕过 wrapper 验证 rustc 本身可用。 该处理不修改 `server-rs/.cargo/config.toml`,也不删除本地 target 缓存。 @@ -29,13 +45,56 @@ sccache: caused by: failed to fill whole buffer rustc -vV ``` -如果只想绕过本次 Cargo 构建的 sccache wrapper,可在 Git Bash 中执行: +如果要保留 sccache 并修复冷启动等待时间,在 PowerShell 中创建或更新 sccache 默认配置: + +```powershell +$configDir = Join-Path $env:APPDATA "Mozilla\sccache\config" +New-Item -ItemType Directory -Force -Path $configDir | Out-Null +@( + "# Windows 本机 sccache 冷启动需要先完成 OSS 缓存读写检查。" + "# 拉长 client 等待 daemon 启动的时间,避免 Cargo 在 rustc -vV 阶段误判超时。" + "server_startup_timeout_ms = 60000" +) | Set-Content -Encoding UTF8 -Path (Join-Path $configDir "config") +``` + +随后清掉 Cargo 曾缓存的失败探测结果,并从冷启动验证: + +```powershell +cd C:\proj\Genarrative\server-rs +sccache --stop-server +Remove-Item -Force target\.rustc_info.json -ErrorAction SilentlyContinue +cargo check -p api-server +``` + +注意:不要在另一个 `cargo` / `rustc` 仍在编译时执行 `taskkill /F /IM sccache.exe /T`。sccache 对 proc-macro crate 会显示 `Server sent UnhandledCompile` 并把请求转交给真实 rustc;如果此时强杀 sccache client/server,可能让 `serde_derive`、`spacetimedb-bindings-macro` 等 proc-macro 编译直接以 `sccache ... exit code: 1` 失败,而 stderr 里看不到真正的 Rust 诊断。这是排障动作打断编译,不是 `spacetime-module` 源码错误。 + +如果只想临时绕过本次 Cargo 构建的 sccache wrapper,可在 Git Bash 中执行: ```bash cd server-rs/crates/spacetime-module RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo check --target=wasm32-unknown-unknown ``` +PowerShell 原生 Cargo 的一次性 wrapper 绕过命令是: + +```powershell +cd C:\proj\Genarrative\server-rs +cargo check -p api-server --config "build.rustc-wrapper=''" +``` + +如果需要验证是否为 OSS/代理冷启动问题,可只在当前 PowerShell 进程中切到本地缓存做对照: + +```powershell +$env:SCCACHE_LOG = "debug" +$env:SCCACHE_ERROR_LOG = "C:\proj\Genarrative\logs\sccache-local-start-error.log" +$env:SCCACHE_DIR = Join-Path $env:TEMP "genarrative-sccache-local-test" +Remove-Item Env:SCCACHE_OSS_BUCKET -ErrorAction SilentlyContinue +Remove-Item Env:SCCACHE_OSS_ENDPOINT -ErrorAction SilentlyContinue +Remove-Item Env:SCCACHE_OSS_KEY_PREFIX -ErrorAction SilentlyContinue +sccache "C:\Users\DSK\.rustup\toolchains\stable-x86_64-pc-windows-msvc\bin\rustc.exe" -vV +sccache --show-stats +``` + 如果需要排查 sccache server 状态: ```bash @@ -44,10 +103,12 @@ sccache --stop-server sccache --start-server ``` -`sccache --stop-server` 本身也可能因为 server 通道已损坏而失败;此时不应阻断本地开发 publish,先使用 wrapper 降级完成验证。 +`sccache --stop-server` 本身也可能因为 server 通道已损坏而失败;只有确认当前没有 `cargo`、`rustc`、`link` 进程后,才用 `taskkill /F /IM sccache.exe /T` 清理残留进程。此时不应阻断本地开发 publish,先使用 wrapper 降级完成验证。 ## 验证 1. `bash -n scripts/dev-rust-stack.sh` -2. `RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo check --target=wasm32-unknown-unknown` -3. 重新运行 `npm run dev:rust`,确认 publish 命令带有 `--build-options="--debug"`。 +2. 冷启动后直接执行 `cargo check -p api-server`,确认不再出现 `Timed out waiting for server startup`。 +3. 执行 `cargo check -p spacetime-module`,确认 proc-macro 依赖和 SpacetimeDB module 都能在 sccache wrapper 下通过。 +4. `sccache --show-stats` 显示 `Cache location oss, name: genarrative-sccache`,确认仍在使用 sccache/OSS 缓存。 +5. 重新运行 `npm run dev:rust`,确认 publish 命令带有 `--build-options="--debug"`。