Beads 独占锁协议(Exclusive Lock Protocol)完全指南:让外部工具安全接管 Dolt 数据库的同步管理
Beads 独占锁协议Exclusive Lock Protocol完全指南让外部工具安全接管 Dolt 数据库的同步管理【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beadsBeads 的独占锁协议Exclusive Lock Protocol允许外部工具以独占方式声明对某个 beads 数据库的管理权从而阻止后台 Dolt 服务器在同步周期内干扰外部工具的操作。本指南以 engdocs/EXCLUSIVE_LOCK.md 为骨架结合仓库源码深入讲解锁文件格式、服务器判定逻辑、过期锁检测原理以及 Go/Shell 集成方式帮助你在确定性执行系统、CI/CD 管道或自定义自动化工具中安全、可预期地接入 Beads 的数据库管理。协议定位解决什么问题Beads 是一个为编码 Agent 提供记忆升级的数据库系统其数据层基于 Dolt一个支持 git 语义的 SQL 数据库。当后台 Dolt 服务器持续运行并周期性执行同步sync操作时如果外部工具需要在一段时间内完全掌控数据库状态二者就会产生冲突。独占锁协议正是在这个场景下设计的协作机制外部工具写入一个锁文件Dolt 服务器在每次同步周期开始时检查该文件一旦发现锁存在就跳过与该数据库相关的所有同步操作把舞台完全交给外部工具。协议官方列举了三类典型使用场景确定性执行系统例如 VibeCoder需要完整控制数据库状态不允许服务器在关键操作中途介入CI/CD 流水线执行原子化 issue 更新时不希望服务器同步操作造成干扰自定义自动化工具自行管理 git 同步工作流需要暂时接管数据库。需要特别强调的是这是一个协作型cooperative协议而非安全机制——它依赖所有参与者自觉遵守约定具体边界见后文边界情况与限制一节。锁文件格式与字段说明独占锁的核心是一个位于工作区内的 JSON 文件路径固定为.beads/.exclusive-lock。其标准格式如下{ holder: vc-executor, pid: 12345, hostname: dev-machine, started_at: 2025-10-25T12:00:00Z, version: 1.0.0 }各字段的含义与约束如下字段类型是否必填说明holderstring必填持有锁的工具名称例如vc-executor、ci-runner用于日志识别pidint必填持有锁的进程 ID是过期锁检测的关键依据hostnamestring必填进程所在主机名用于区分本地锁与远程锁started_atRFC3339 时间戳必填锁的获取时间例如2025-10-25T12:00:00Zversionstring可选锁持有工具自身的版本号便于排障时定位工具版本对应文档中的 API 参考Go 侧将该结构定义为ExclusiveLock其 JSON 标签与上表一一对应// ExclusiveLock represents the lock file format type ExclusiveLock struct { Holder string json:holder PID int json:pid Hostname string json:hostname StartedAt time.Time json:started_at Version string json:version }在仓库中.exclusive-lock还被纳入了运行时文件的追踪与 gitignore 管理范畴cmd/bd/doctor/tracked_runtime.go将其列为需要追踪的运行时文件之一见 cmd/bd/doctor/tracked_runtime.go而cmd/bd/doctor/gitignore.go则将其列入忽略列表见 cmd/bd/doctor/gitignore.go这从侧面印证了该文件的临时性 运行态定位锁文件不应被误提交进版本库但 doctor 工具需要感知它的存在。服务器行为每个同步周期开头的四路判定Dolt 服务器在每个同步周期开始时检查独占锁。依据锁文件的状态服务器会走四条不同的路径无锁文件服务器正常执行同步操作有效锁进程存活服务器跳过该数据库的所有操作过期锁进程已死服务器移除锁文件然后正常继续同步损坏的锁JSON 非法服务器采取 fail-safe 策略跳过该数据库。这里有一个重要的时序细节服务器只在同步周期开始时检查锁。如果锁是在某个同步周期进行中才被创建的当前这个周期仍会执行完毕但从下一个周期开始数据库会被跳过。换句话说锁的生效存在最多一个同步周期的延迟集成方在设计时序时应当把这一点纳入考量。服务器日志中与此相关的典型输出如下Skipping database (locked by vc-executor) Removed stale lock (vc-executor), proceeding with sync Skipping database (lock check failed: malformed lock file: unexpected EOF)排障时可以查看服务器日志文件.beads/dolt/sql-server.log来确认锁相关事件的具体经过。过期锁检测ESRCH 判定与 fail-safe 原则过期锁检测是协议中最微妙的部分其判定规则如下hostname 与当前机器一致不区分大小写且PID 在本机不存在对 PID 发起探测返回 ESRCH时判定为过期锁服务器只在能确切证明进程已死ESRCH时才移除锁。如果服务器对目标 PID 的探测因权限不足而返回 EPERM它会把锁当作有效锁处理并跳过数据库——这种 fail-safe 设计避免了误删其他用户持有的锁远程锁hostname 与本机不同永远被假定为有效因为服务器无法验证远程进程的状态所以远程主机上残留的过期锁不会被自动清理必须人工手动移除。从源码层面看仓库在internal/linear/synclock.go中实现了同源的进程存活判定函数IsProcessAlive见 internal/linear/synclock.go在 Unix 平台上通过向目标 PID 发送 signal 0 来探测pid 0时直接返回 falseWindows 平台则使用OpenProcess实现等价判定。这与文档中ESRCH 判死、EPERM 存疑的语义一致——signal 0 探测本质上就是只探测、不打扰的进程存在性检查。当过期锁被成功移除时服务器会记录日志Removed stale lock (holder-name), proceeding with sync。集成示例Go 与 Shell 双语言实操创建锁Go官方推荐的 Go 创建方式通过types.NewExclusiveLock构造锁对象再以缩进 JSON 形式写入.beads/.exclusive-lockimport ( encoding/json os path/filepath github.com/steveyegge/beads/internal/types ) func acquireLock(beadsDir, holder, version string) error { lock, err : types.NewExclusiveLock(holder, version) if err ! nil { return err } data, err : json.MarshalIndent(lock, , ) if err ! nil { return err } lockPath : filepath.Join(beadsDir, .exclusive-lock) return os.WriteFile(lockPath, data, 0644) }NewExclusiveLock(holder, version string) (*ExclusiveLock, error)会为当前进程自动填充pid、hostname、started_at等运行时字段写文件时使用0644权限即可该文件本身不承载安全职责。释放锁Go释放锁即是删除锁文件func releaseLock(beadsDir string) error { lockPath : filepath.Join(beadsDir, .exclusive-lock) return os.Remove(lockPath) }创建锁Shell对于不依赖 Go 工具链的脚本场景可以直接用 Shell 拼装 JSON 并利用$$当前 PID、$(hostname)、date等内建能力生成锁文件#!/bin/bash BEADS_DIR.beads LOCK_FILE$BEADS_DIR/.exclusive-lock # Create lock cat $LOCK_FILE EOF { holder: my-tool, pid: $$, hostname: $(hostname), started_at: $(date -u %Y-%m-%dT%H:%M:%SZ), version: 1.0.0 } EOF # Do work... bd create My issue -p 1 bd update bd-42 --claim # Release lock rm $LOCK_FILE注意started_at使用date -u生成 UTC 时间并格式化为 RFC3339与协议要求一致。推荐模式善用清理句柄锁的正确释放直接关系到后续同步能否恢复因此官方强烈建议使用清理句柄defer / trap保证锁在异常退出时也能被释放func main() { beadsDir : .beads // Acquire lock if err : acquireLock(beadsDir, my-tool, 1.0.0); err ! nil { log.Fatal(err) } // Ensure lock is released on exit defer func() { if err : releaseLock(beadsDir); err ! nil { log.Printf(Warning: failed to release lock: %v, err) } }() // Do work with beads database... }即使工具进程崩溃导致锁未能释放服务器侧的过期锁检测ESRCH 判死也能兜底清理本地残留锁这构成了一套主动释放为主、服务器兜底清理为辅的完整闭环。边界情况与限制多个写入者、无服务器时独占锁协议只能阻止 Dolt 服务器干扰它不提供以下保证多个外部工具之间的互斥事务隔离或 ACID 保证对直接文件系统操作的防护。如果需要协调多个工具必须自行实现锁机制例如参考仓库中internal/linear/synclock.go基于 flock 的内核锁实现它通过lockfile.FlockExclusiveBlocking/FlockExclusiveNonBlocking提供真正的进程互斥语义并额外发布pid/started元数据用于争用诊断见 internal/linear/synclock.go。独占锁协议与之不同它只是一个标记文件 约定层面的协作协议。Git WorktreesDolt 原生支持 git worktree。独占锁协议与 worktree 支持是相互独立的机制互不影响。远程主机如前文所述来自远程主机的锁永远被假定有效因此远程过期锁不会自动清理必须人工删除。这在多机共享同一个数据库目录的部署形态下需要格外留意。锁文件损坏如果锁文件因写入中断等原因变成非法 JSON服务器会 fail-safe——跳过该数据库你需要手动修复或删除锁文件才能恢复同步。集成验证五分钟跑通全流程文档给出了一个可复现的验收流程用于确认你的集成是否生效启动 Dolt 服务器执行bd dolt start创建锁用你的工具生成.beads/.exclusive-lock验证服务器跳过检查服务器日志应出现Skipping database消息释放锁删除.beads/.exclusive-lock验证服务器恢复检查服务器日志确认恢复正常同步周期。这套流程既可用于开发阶段的联调也可作为 CI 中对该协议进行回归验证的冒烟测试脚本。安全考量协作协议 ≠ 安全机制锁文件不安全任何进程都可以创建、修改或删除它PID 复用理论上可能引发误判概率极低尤其在叠加 hostname 校验之后这是一个协作协议不是安全机制——不要用它承载任何安全边界。API 参考速览协议对外暴露的核心 Go API 如下// NewExclusiveLock creates a lock for the current process func NewExclusiveLock(holder, version string) (*ExclusiveLock, error) // Validate checks if the lock has valid field values func (e *ExclusiveLock) Validate() error // ShouldSkipDatabase checks if database should be skipped due to lock func ShouldSkipDatabase(beadsDir string) (skip bool, holder string, err error) // IsProcessAlive checks if a process is running func IsProcessAlive(pid int, hostname string) bool其中IsProcessAlive的进程存活探测在仓库中已有同语义实现internal/linear/synclock.go中的IsProcessAlive(pid int) boolUnix 下基于 signal 0可直接作为理解协议底层判活逻辑的参考实现。结语独占锁协议以一个 JSON 文件 一个服务器检查约定的极简形态解决了外部工具与后台 Dolt 服务器之间的接管权交接问题。其设计精髓在于三点协作而非强制不承诺互斥与安全、fail-safe 而非激进攻略EPERM 存疑时宁可不清理、可观测完善的服务器日志与工具字段。无论你是构建确定性执行系统、CI 流水线还是自定义自动化工具只要遵守创建锁 → 执行操作 → 释放锁含清理句柄兜底的规范流程就能稳定地将 Beads 数据库纳入自己的编排体系。更深入的工作流指引可继续查阅仓库根目录的 AGENTS.md 与 README.md以及 examples/ 目录下的集成示例。【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →