From bf59e3f222933eecab8648aad102f0ce45ca74b8 Mon Sep 17 00:00:00 2001 From: Feng Ruohang Date: Tue, 15 Sep 2026 12:16:45 +0800 Subject: [PATCH] docs: record retirement execution and blocked Linux acceptance Signed-off-by: Feng Ruohang --- docs/investigations/access-tiering-revert.md | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/docs/investigations/access-tiering-revert.md b/docs/investigations/access-tiering-revert.md index cb2e43e9f..30f70407c 100644 --- a/docs/investigations/access-tiering-revert.md +++ b/docs/investigations/access-tiering-revert.md @@ -4,6 +4,8 @@ 初稿审查时(2026-09-15 03:20 UTC),最终候选尚未移植到远端基线、尚未冻结 PR head,合并前全量检查与三次有效 Linux 运行尚未执行,本变更尚未合并。后续执行状态以承载本记录的 PR 及其绑定提交的验收记录为准;下文的历史实验不替代这些检查。 +**当前执行状态:** 回退、普通版本 DELETE 调和、扫描复用及文档已提交到 [Draft PR #188](https://github.com/pgsty/silo/pull/188)。本地与 CI 检查通过,但第二轮有效 Linux 升级实验出现 DELETE204 后的 HEAD/GET503,合并验收未通过。当前不合并、不发布,main 的五份旧修改仅归档,尚未清理。详情见第 9、10 节。 + ## 1. 引入的目标和实际范围 [@mrjavadseydi](https://github.com/mrjavadseydi) 在 [PR #60](https://github.com/pgsty/silo/pull/60) 提出了基于 GET 频率的本地池间分层。成功 GET 更新有界滚动计数,后台调度器把热对象提升到配置中的首个池,把已经迁移且变冷的对象降到末个池。功能默认关闭,至少需要两个池;它与普通生命周期过期、远端对象存储 transition、rebalance 和 decommission 是不同机制。 @@ -114,3 +116,50 @@ Claude Code Opus 5 / max 的五轮实现评审要求补齐退役兼容、说明 全量 cmd/internal、相关 race、构建、vet、lint、生成文件和兼容检查,以及上述 Linux 验收,绑定最终候选的实际 SHA。若纳入新的远端提交,重新记录基线与 head,复核变更并重跑受影响验收。文档与原始测试记录各自保留其对应版本,不篡改旧失败、不用新通过覆盖旧记录。 逐节点滚动升级未通过既有二进制校验检查,采用[协调停机方案](../bucket/lifecycle/access-tiering-removal.md#before-upgrading-a-build-with-access-tiering)。实验使用单个 Docker Linux VM 和 tmpfs;正式 tag、包、镜像、跨主机及生产部署仍是独立交付。未验证全部重复 UUID 或运行时统计守恒应如实披露,不能反向引入自动搬回/清理需求或无关重构。 + +## 9. 执行后记:最终基线、恢复窗口与验收 + +本次实际交付由 [PR #188](https://github.com/pgsty/silo/pull/188) 承载。选择的远端基线为 `89637554d60c27cfc51d2281d0a4fe15e415f06d`,移植没有包含本地独立 IAM/超时提交 `ebc9937d9`。前三项实现和历史文档逐提交通过 stable patch-id 对照;虚拟补回独立 IAM 差异后,完整树与原审查分支一致。 + +首次本地 lint 发现新增回调选择分支触发 `gocritic/ifElseChain`,因此追加等价的无表达式 `switch` 改写,保持 marker、指定版本和普通元数据查找的条件顺序及分支体。重新固定的代码候选为 [`41aa84609`](https://github.com/pgsty/silo/commit/41aa84609754769cfb1861d7fd060c2e84182b98)。这一提交上,全量 cmd/internal 得到 6,428 个测试及子测试通过、166 个跳过,50 个有测试的包通过;相关 race 得到 283 个测试及子测试通过。`make build`、全包构建、vet、lint、生成文件及 rebrand/compat 检查均通过。[Go CI](https://github.com/pgsty/silo/actions/runs/34925534139)、[DCO](https://github.com/pgsty/silo/actions/runs/34925534110)、[VulnCheck](https://github.com/pgsty/silo/actions/runs/34925534142) 和[发布流水线的测试运行](https://github.com/pgsty/silo/actions/runs/34925534198)共 11 项检查通过;后者没有发布正式制品。 + +第一次最终候选停池实验 `dcd5c2e5` 在源版本保全断言后失败:停掉另一池返回 `503 SlowDownRead`,源四盘版本保留;恢复后 DELETE 成功,节点 0/2 的 HEAD/GET 返回 404,节点 1 返回 503。DELETE 成功由脚本已通过的 204 断言确定,原输出没有单独保存该次 DELETE 响应。此次失败如实保留,不能把后来的成功写回原记录。 + +复核发现,`ListBuckets` 以及位于源池的现存版本 GET,不能证明每个协调节点对另一池的读取连接已经恢复。随后进行了旧基线与候选的同拓扑对照,探测的是从未写入过的随机 UUID,并且在这些探测之前没有执行任何 DELETE: + +| 高时间分辨率对照 | 桶列表和现存版本 | 从未写入版本的 HEAD/GET | 观察到的恢复窗口 | +| --- | --- | --- | --- | +| `20502a2f`,旧基线 `89637554d` | 三节点均为 200 | 节点 0/2 为 404,节点 1 为 503 SlowDownRead,连续 16 组 | 从重启后的观察循环起算约 1.60–2.50 秒 | +| `246aaf77`,候选 `41aa84609` | 三节点均为 200 | 同样是节点 1 的 503,连续 11 组 | 约 1.67–2.30 秒 | + +两边在缺失版本全节点连续三轮返回 404 后执行 DELETE,均得到 204、全节点 HEAD/GET 404、目标 UUID 在八盘均不存在且其他版本可读。另有两次较低时间分辨率诊断未捕捉到窗口,同样保留;这四次诊断不计入三次升级验收。 + +这给出了基线在零 DELETE 下的正向复现,证明原恢复条件不足。`getLatestObjectInfoWithIdx` 的读选择函数与基线文本相同:现存副本可以遮蔽另一池的读错误;缺失版本则必须确认所有池,不可读时返回 503。Claude 复核后同意修正实验准备条件并继续验收,明确反对把这一路径的 503 改成 404。最初失败没有瞬时 RPC 全貌,不能逐请求追溯每条连接;这些对照也不能给 `83676ca2` 归因。 + +修订后的验收在升级/恢复后逐节点探测从未写入的 UUID,记录首次全 404 时刻,要求连续三轮全 404;并列保存各节点 `admin info` 的全盘状态。最多等待 30 秒,超时仍失败,DELETE 之后仍严格要求 204/404,不把 503 纳入通过条件。后续失败保留实验资源供即时取证,再受控清理。 + +修订准备条件后的独立停池验收 `40a59b3b` 通过:离线 DELETE `503 SlowDownRead`,源四盘版本保留;恢复门约 1.48 秒完成,DELETE `204`,三节点 HEAD/GET `404`,目标在八盘均不存在,另一版本仍可读。恢复早期 `admin info` 中也记录到了各节点不同的离线盘视图,最后恢复为全盘正常。 + +完整升级验收随后实际进行了三次尝试: + +| 尝试 | 运行 | 结果与证据边界 | +| --- | --- | --- | +| 1 | `83f88c59` | 准备失败,未启动候选。旧版 rebalance 报 Completed、搬移版本数为 0;源池占用约 6.5%,到平均空闲目标的差值约 3.13%,落入代码既有 5% 容差。增加造数从 64 到 192 个 2 MiB 版本后再试;本次仍计入五次总尝试上限。 | +| 2,第一轮有效运行 | `ea58d0c5` | 通过。实际 rebalance 中断产生跨八盘的重复版本;停机复制同一数据供旧版对照。旧版 DELETE204 后仍可读;候选 DELETE204 后四节点立即及后续固定间隔 HEAD/GET 均404,八盘目标清除、另一版本四节点可读;旧 ILM/生命周期编辑和真实缓存 v9→v8 通过。 | +| 3,第二轮有效运行 | `2059bc6b` | **候选失败,阻断合并。** 两阶段逐节点缺失版本连续三轮404、admin info全盘ok之后,DELETE明确204(约12.98ms);节点2随后的HEAD503/GET503 SlowDownRead,另外三节点404;八盘快照均无目标,首次重试及后续采样全404,其他版本四节点可读。首次失败保留,不因重试恢复改判。 | + +第三次尝试发生后停止剩余验收,保留原容器、卷、元数据与响应时序进行诊断。不能把四节点顺序探测中的“节点2异常”直接解释为永久节点故障:它也可能与采样时间有关。随后在保留环境中,对三个额外重复版本做并发、不同顺序的“刚删 UUID / 从未写入 UUID”对照,候选稳定期均为204/404,未复现;旧版克隆数据的双次 DELETE 对照则遇到 `SlowDownWrite`,没有完成其全部断言。这些是诊断结果,不补入有效升级通过计数,也不证明第三次尝试已解释。 + +为观察逐盘返回,另在独立临时工作树编译仅增加日志的诊断二进制,**没有进入 PR**。它证明了第二层准备检查盲点:`getObjectFileInfo` 的四个响应信号中,可以只有两个实际 `file version not found`,其余两个是被跳过的盘所保留的 `errDiskOngoingReq`;`objectQuorumFromMeta` 的预期读 quorum 为2,因而仍可返回404。同期 `admin info` 汇集各服务器本地盘态为ok,不能证明请求节点到各盘的路径都可用。一次诊断 DELETE 的逐盘返回为 `[nil, nil, drive not found, drive not found]`,达不到写 quorum 3,故返回 `SlowDownWrite`。 + +Claude 撤回了此前“逐节点三轮404已是最强全池准备条件”的表述,同意这只能证明读 quorum,不能证明全盘可达或写 quorum。诊断给出了候选机制,但**第三次尝试失败瞬间没有逐请求逐盘日志,仍不足以确定其具体原因**;不能把后来稳定期的成功、诊断中的配额不足,或对错误名的解释当成该次故障的直接证据。 + +## 10. 停止位置与恢复资料 + +截至本记录交付,代码仍为 `41aa84609`;后续提交仅记录本次执行,不改变已测试的生产代码。有效升级运行是一通过、一失败,未满足三次有效运行全部通过的约定;总尝试3次,并未通过继续补跑消耗剩余次数来冲淡失败。`2059bc6b` 和先前的 `83676ca2` 均保持 **OPEN**。Claude 与 Codex 的最终裁定是 **NO-GO for merge**,不把证据不足升级为“已修复”“既有问题”或“暂态”。实际 PR 合并状态始终以 [#188](https://github.com/pgsty/silo/pull/188) 为准。 + +主工作区原五文件的完整内容、二进制补丁和 SHA-256 已归档;另有可达 Git 引用 `refs/archive/access-tiering-main-five-files-20260915`,指向快照 `c7fbfc6ada0f0f2abcbe8c0a9681f07e12dafe52`。逐文件核验快照与原已审内容一致。由于最终验收未通过,未执行五文件恢复,也未移动或改写独立 IAM 提交 `ebc9937d9`。这不是“三份变体已经归一”的完成声明;唯一待交付候选仍在 PR 分支,旧变体冻结等待验收裁定。 + +本机执行资料归档在 `~/.codex/outputs/silo-access-revert-assessment-20260915/final-execution/`:保存了每次尝试、旧/新基线对照、二进制 SHA-256、准备条件、源/目的全盘元数据、诊断补丁、独立评审意见,以及受控清理记录。原始失败记录不覆写;保存的诊断卷内容用于继续调查,不是生产数据或发布制品。 + +继续推进需要一次能区分机制的取证:在条件可控的升级实验中,于失败请求当时记录每池每盘的真实应答和错误类型,并同时读刚删版本与从未写入版本;明确区分盘面不同步、请求节点的不可用路径与其他原因。若四盘均真实应答仍返回503,应沿错误归约/元数据路径定位;若盘不可用,应查明连接或初始化状态,并验证准备条件。后续成功本身不能关闭本次失败,更不能通过把不可判定的503改成404来满足验收。正式发布、制品和生产部署继续作为独立交付。