十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Beads 中 `bd recompute-blocked` 命令全解析:依赖图驱动的 is_blocked 标志全量重算与修复

Beads 中 `bd recompute-blocked` 命令全解析:依赖图驱动的 is_blocked 标志全量重算与修复 Beads 中bd recompute-blocked命令全解析依赖图驱动的 is_blocked 标志全量重算与修复【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beadsbd recompute-blocked是 Beads 提供的一条维护命令用于对仓库中每个 issue 与 wisp 的反规范化字段 is_blocked执行一次无条件的全量重算并将结果落库提交。它在本地写入与拉取pull后的增量重算因异常被跳过、导致该标志失真时提供一条幂等、可跨存储模式使用的修复路径。读完本文你将理解 is_blocked 的派生机制与失效场景、该命令的完整执行流程、三种存储模式下的路由差异以及它与bd doctor --fix的配合方式并能在实际故障中正确选用bd recompute-blocked --json等输出形态完成修复与自动化接入。is_blocked 是什么依赖图派生出的反规范化标志在 Beads 的数据模型中issue 与 wisp工作单元之间存在依赖关系分别记录在dependencies与wisp_dependencies表中。一个条目的 is_blocked 表示它当前是否被未完成的上游依赖阻塞是从依赖图中派生出来的状态而非独立录入的事实。正因如此它被设计成反规范化存储——即把派生结果物化到issues与wisps表的is_blocked列中供bd ready等查询路径直接信任使用避免每次读取都现场遍历依赖图。is_blocked 的正常维护路径有两条见 recompute-blocked.md本地写入路径创建、更新、关闭 issue/wisp 等操作在写入时同步维护该标志拉取后的增量重算pull 合并完成后会针对合并所改变的范围merge diff 的作用域执行一次局部重算。失效场景为什么标志会变脏增量重算依赖合并推进了 HEAD这一前提。以下场景会绕过它使标志失真合并已提交但重算失败重算在 merge commit 落地之后才执行若此时重算过程失败后续再次 pull 因为没有可合并的新内容而不会再触发任何重算对应仓库内部问题跟踪编号 bd-6dnrw.37手工解决的冲突拉取operator 手工解决冲突后合并路径被打断同样跳过了增量重算。失真的后果是直接的bd ready信任该列于是过期的值会静默隐藏可就绪的工作或把已阻塞的工作显示为可执行。这两种错误方向对依赖代理coding agent来说都是危险的误判。命令概览与基本用法bd recompute-blocked属于维护maint命令组其使用形式为bd recompute-blocked [flags]常用调用示例来自 cmd/bd/recompute_blocked.gobd recompute-blocked # 修复过期的 is_blocked 标志 bd recompute-blocked --json # 机器可解析的输出{rows_corrected: N}关键行为约定无条件全量重算不依赖任何 merge 是否推进 HEAD直接对全表执行一遍完整重算幂等在一致consistent的数据库上执行修正行数为 0不产生任何变更自动提交只要有行被修正就会将结果作为一次 Dolt 提交落库提交信息统一为bd: recompute is_blocked (full)全模式可用embedded、server、proxied-server 三种存储模式均可运行——这一点与bd doctor不同后者仅限 server 模式。命令在入口处还会调用CheckReadonly(recompute-blocked)进行只读保护检查并以metrics.NewCommandEvent(recompute-blocked)上报一次命令遥测事件见 cmd/bd/recompute_blocked.go。输出形态人读文本与机器可解析 JSON命令通过renderRecomputeBlocked统一渲染结果文本与 JSON 两种形态共用同一份渲染逻辑保证下游调用方读取的形状不会因模式不同而漂移见 cmd/bd/recompute_blocked.go未指定--json时修正 0 行输出is_blocked already consistent — nothing to recompute.修正 N 行输出Recomputed is_blocked: N row(s) corrected.指定--json时输出{rows_corrected: N}便于脚本与 Agent 直接解析。三模式路由从 CLI 到存储后端命令的RunE首先判断运行环境然后分派到对应实现见 cmd/bd/recompute_blocked.goproxied-server 模式若检测到使用了 proxied serverusesProxiedServer()调用runRecomputeBlockedProxiedServerembedded / 直连 server 模式对存储做类型断言storage.UnwrapStore(store).(storage.BlockedRecomputer)若后端不支持该能力则报错storage backend does not support is_blocked recompute否则调用RecomputeAllBlocked(ctx)并渲染结果。BlockedRecomputer是定义在 internal/storage/storage.go 中的接口只有一个方法type BlockedRecomputer interface { RecomputeAllBlocked(ctx context.Context) (int, error) }该接口的文档注释明确与依赖 merge 推进 HEAD 的作用域重算不同全量重算不依赖 merge 推进 HEAD因此能够恢复被跳过的重算留下的过期列且幂等——一致的数据序修正 0 行。embedded 模式的实现EmbeddedDoltStore 在 internal/storage/embeddeddolt/version_control.go 中实现了RecomputeAllBlocked其接线正确性由 internal/storage/embeddeddolt/blocked_recompute_test.go 中的TestEmbeddedRecomputeAllBlockedWiring与TestEmbeddedRecomputeAllBlockedDirtyGraphIsTyped验证。直连 server 模式的实现DoltStore 的实现在 internal/storage/dolt/store.go 中。值得注意的工程细节全量重算的批量 UPDATE 每条携带五个相关的 EXISTS 子查询在负载较高的共享服务器上单个批次可能超过连接池默认的每 I/O 超时默认 10s见 buildServerDSN导致修复以i/o timeout失败且重试同样失败bd-bn8jo。因此实现会通过openLongTimeoutConn()打开一条专用长超时连接SetMaxIdleConns(0)并db.Conn(ctx)固定单条物理连接分支状态是连接作用域的BeginTx 必须跑在刚被取出的那条连接上在重算读写之前通过pinStoreBranch复现存储当前激活的分支避免新连接默认落到 Dolt 默认分支上be-b0am。proxied-server 模式的实现runRecomputeBlockedProxiedServer见 cmd/bd/recompute_blocked_proxied_server.go本身不重新实现修复逻辑守卫、不动点重算、暂存集合与提交信息全部来自共享代码versioncontrolops.RecomputeAllBlockedOnConn因此两种模式不会算出不同的标志、也不会落地不同的历史。模式特有的只是如何拿到连接。它运行在固定的非事务连接上而不是走uow.RunTx*原因有二修复在事务提交后还需要执行DOLT_ADD/DOLT_COMMIT存储过程而 Dolt 拒绝在显式事务内运行存储过程uow 提交路径使用DOLT_COMMIT(-Am, …)暂存全部内容而本修复必须只暂存issues表——它从依赖图派生一个标志没有理由把一个无关的脏工作区卷进自己的提交这正是脏图守卫在读取侧要防止的事。此外退出码是下游的完整契约wh-bridge-sync 在超时上限内运行本命令将退出码 124 视为服务端仍在运行因操作幂等而最多重试 3 次成功为 0任何失败服务器不可达、脏图、查询被杀都是非零的 HandleError实现不会凭空捏造成功。底层核心流程守卫 → 全量不动点重算 → 提交所有模式的修复体共享 internal/storage/versioncontrolops/blocked_recompute.go 中的RecomputeAllBlockedOnConn其流程为BeginTx开启事务GuardedRecomputeAllBlockedInTx先执行守卫再执行重算二者处于同一事务提交事务仅当修正行数changed 0时才StageAndCommit提交——暂存集合只有issues提交信息固定为bd: recompute is_blocked (full)。第一步脏图守卫GuardBlockedRecomputeWorkingSet见 internal/storage/issueops/blocked_consistency.go是事务内执行的第一条语句这刻意为之它必须观察到重算将要读取的同一个工作区否则守卫的就不是正在被修复的那个数据库。它通过查询dolt_status找出图相关表中存在未提交变更的子集若非空则拒绝重算并返回ErrBlockedRecomputeDirtyGraph需要先提交或丢弃这些表的待定变更才能继续commit or discard pending changes to tables first配套的DirtyGraphFingerprint为未提交图状态生成指纹脏表集合 每个脏表中变更行的身份用于区分卡住的工作区与繁忙的工作区繁忙工作区的指纹会不断变化卡住工作区的指纹则永远字节一致。注意其契约返回空串且无错误表示图表是干净的该值不可当作指纹参与跨观测比较错误表示证据不可得如旧引擎缺少 dolt_diff 表函数、读权限被撤销调用方必须拒绝升级判断而非假设任一答案。第二步全量不动点重算RecomputeAllIsBlockedInTx见 internal/storage/issueops/blocked_consistency.go先列出issues与wisps的全部 IDwisps 表不存在时视为空表然后进入不动点循环对issues经dependencies执行一次全表 markunmark 扫描对wisps经wisp_dependencies执行一次全表 markunmark 扫描两轮修正行数求和若本轮修正为 0 则循环收敛记录日志快照并返回总数否则继续下一轮——因为一轮中父项的翻转会在下一轮级联到子项每一次修正都计入总数。性能层面的关键实现决策与作用域重算不同全量修复使用非批量的半连接semi-join语句markAllBlockedSQL/unmarkAllBlockedSQL。因为 ID 列表按构造覆盖了全部行IN 分批只会徒增语句数而批量模板的 OR-of-correlated-EXISTS 形态无法被引擎去关联化——逐外行的子查询执行使全量修复在快硬件上耗时约 80 语句秒、在小云 CPU 上超过 600 秒bd-t9ypt。mark 语句的谓词要点见 internal/storage/issueops/blocked_consistency.go将is_blocked置 1 的条件当前is_blocked 0且状态既非closed也非pinned且存在未满足的上游依赖置 0 的反向语句同理当前is_blocked 1且不存在阻塞它的依赖或状态为closed/pinned两个方向都附带updated_at updated_at的无操作更新使被修正的行进入变更集不伪造更新时间戳。第三步提交与暂存集合BlockedRecomputeStagedTables()只返回{issues: true}。注释解释得透彻is_blocked 虽然也存在于 wisp 表但 wisp 表被dolt_ignore忽略、永远无法暂存而暂存任何更宽的范围都会把无关的脏工作区扫进一个本应只包含派生标志的提交。每次调用都返回新 map因为StageAndCommit的参数是可变集合。提交信息常量BlockedRecomputeCommitMsg bd: recompute is_blocked (full)对所有模式统一因此阅读dolt_log无法区分是哪种模式执行的修复——这恰恰是设计意图修复与模式无关其历史条目也必须如此。author参数可以为空此时省略--author由服务器将提交归属于当前会话——这是 proxied-server 平面的正确默认值其每个其他提交uow.Tx.Commit同样不带作者持有已配置提交者身份的存储则传入该身份。另外注意即使暂存步骤报错返回的修正数依然有意义——行确实在工作区中被修正了只是历史条目失败此时若报 0 就是在对读者撒谎。与bd doctor的关系两种修复入口bd doctor提供名为 Blocked State 的检查项BlockedConsistencyCheckName见 cmd/bd/doctor/blocked.go其底层同样使用issueops.CountIsBlockedInconsistenciesInTx统计 is_blocked 与依赖图不一致的行数统计为 0 → 状态 OKis_blocked flags consistent with dependency graph统计 0 → 状态 WarningN issue/wisp row(s) have a stale is_blocked flag — bd ready may hide ready work or show blocked work并附带修复建议Run: bd doctor --fix (or bd recompute-blocked, which also works in embedded mode)。也就是说bd doctor负责检测bd doctor --fix与bd recompute-blocked都指向同一份全量修复后者在 embedded 模式下也可用这是它与仅限 server 模式的bd doctor的关键差别。二者对同一底层修复的共享由 internal/storage/versioncontrolops/blocked_recompute.go 及RecomputeAllBlocked的注释共同印证。自动化集成与运维建议结合上文契约在实际运维中可以这样使用该命令例行自检定期运行bd doctor观察 Blocked State 检查项或直接运行bd recompute-blocked——在一致数据库上它什么都不改幂等特性使它天然适合放进定时任务故障修复发现bd ready显示异常隐藏了可就绪工作或显示了被阻塞工作时先bd recompute-blocked --json确认rows_corrected是否为 0再决定是否需要进一步排查合并路径脚本集成使用--json输出解析rows_corrected如需判断是否仍在服务端运行可参照 wh-bridge-sync 的约定——把超时退出码 124 当作仍在运行因操作幂等可安全重试上限 3 次脏工作区处理若命令报ErrBlockedRecomputeDirtyGraph图相关表存在未提交变更需先提交或丢弃这些待定变更再重试不要强行绕过守卫限定影响面修复只暂存issues表并单独提交不会把无关的脏工作区卷进本次历史提交信息固定为bd: recompute is_blocked (full)可在dolt_log中追踪历次修复记录。小结bd recompute-blocked是 Beads 维护命令组中对派生状态一致性问题的最终兜底它把依赖图到is_blocked列的物化过程以全量、幂等、带守卫、固定提交信息的方式重放一遍统一了 embedded、server 与 proxied-server 三种模式的修复语义并与bd doctor的检测能力形成检测 修复的完整闭环。理解它的失效模型增量重算被跳过、执行流程守卫 → 不动点重算 → 单表提交与契约细节JSON 输出、退出码、脏图守卫即可在 Agent 工作流中安全地自动化这一维护操作。【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表