Files
Genarrative/docs/technical/SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md

115 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SpacetimeDB publish sccache 降级处理
## 背景
Windows 本地执行 `npm run dev:rust``spacetime publish` 时,`spacetime` 会在内部调用 Cargo 构建 `server-rs/crates/spacetime-module`。当前本地开发 publish 会追加 `--build-options="--debug"`,让 SpacetimeDB CLI 用 debug 构建参数编译模块。因为 `server-rs/.cargo/config.toml` 配置了 `rustc-wrapper = "sccache"`,即使当前 shell 没有设置 `RUSTC_WRAPPER`Cargo 仍会先执行 `sccache rustc -vV`
当本机 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
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 冷启动超时时,优先保留 `sccache` wrapper并修复 sccache daemon 的启动等待时间;只有在排除 sccache 本身问题时,才临时绕过 wrapper 验证 rustc 本身可用。
该处理不修改 `server-rs/.cargo/config.toml`,也不删除本地 target 缓存。
## 手动排障命令
优先确认 rustc 本身可用:
```bash
rustc -vV
```
如果要保留 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
sccache --show-stats
sccache --stop-server
sccache --start-server
```
`sccache --stop-server` 本身也可能因为 server 通道已损坏而失败;只有确认当前没有 `cargo``rustc``link` 进程后,才用 `taskkill /F /IM sccache.exe /T` 清理残留进程。此时不应阻断本地开发 publish先使用 wrapper 降级完成验证。
## 验证
1. `bash -n scripts/dev-rust-stack.sh`
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"`