fix(cache): 缓存损坏或临时云存储错误时降级重建 - #32
Conversation
代理链路不稳定导致 S3 body 截断,出现两类故障: 1. ZstdError:从 S3 下载的 .tar.zst 残缺,本地解压失败 2. IncompleteBody:上传阶段 body 与 Content-Length 不一致 修复: - cache.py load():本地缓存 ZstdError 时删除本地并从云端重新下载; 云端缓存也损坏时清理本地并 re-raise,让 target.py 走重建路径 - target.py execute():NORMAL 模式下 load() 抛出 ZstdError 时 fallback 到重新构建并保存新缓存,不再 crash job - 上传失败(CloudStorageError)从 sys.exit(1) 改为 warning, 缓存上传失败不影响构建结果 - 新增对应测试:corrupt local cache fallback、corrupt cloud cache re-raise Co-Authored-By: via Moxt <noreply@moxt.ai>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
1 similar comment
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
127df0a to
4cade92
Compare
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
解决什么问题
quack S3 缓存链路依赖第三方代理,近期在 merge queue 中多次出现同一类不稳定故障:
.tar.zst,触发zstandard.ZstdError: did not decompress full frameIncompleteBody,即实际 body 长度小于Content-Length这些属于开发者无法直接控制的 transient 基础设施问题,不应该让业务 job 随机失败;但配置、权限、bucket 不存在等开发者能感知并修复的问题也不应该被 catch 隐藏。
这版补上了 boto3/botocore transfer wrapper 的真实异常路径,并把 catch 边界收敛到 SDK 错误基类,transient 降级仍由白名单统一判断。
证据背景
2026-07-08 下午(Asia/Shanghai)merge queue 连续 4 次被同一个
sandbox:generate缓存链路拖挂。前三次是下载后的 zstd 解压失败,第四次扩散成上传阶段IncompleteBody:project-lint、sandbox-build依赖sandbox:generate,从云端下载缓存后解压失败。IncompleteBody失败,说明不仅下载会拿到残缺 body,上传路径也会被代理截断。关键日志形态:
当时 GitHub Status 为 All Systems Operational;结合连续 run、同一缓存 target、多 job 扩散,以及下载/上传两端都出现 body 截断,判断问题在 quack S3 缓存经过的第三方代理链路,而不是业务代码或 GitHub Actions 本身。
受影响 job 包括但不限于
project-lint、sandbox:build、sandbox-pi-cloudflare:build、sandbox-test。这些 job 对sandbox:generate缓存有依赖,所以缓存层 transient failure 会随机阻塞 merge queue。怎么解决
CloudStorageTransientError,只把明确的 transient 云存储错误降级处理:IncompleteBody500/503/SlowDown/ throttling 等临时服务端错误CloudStorageError/CloudStorageTransientError,具体是否 transient 由错误码、网络异常和 wrapped error chain 的白名单判断。CacheCorruptionError,Target.execute()只处理缓存领域错误和 transient 云存储错误,不再直接依赖 zstd/boto3 底层异常。AccessDenied、认证错误、bucket/path 配置错误等非 transientCloudStorageError继续 fail-fast。验证
uv run ruff format --checkuv run ruff checkuv run basedpyrightuv run pytestuv run pytest src/quack/utils/cloud_test.py src/quack/cache_test.py src/quack/models/target_test.pygit diff --checkuv run quack testuv run quack testuv run quack test --cache=false