dsh-single-instance-guard:DSH 单实例锁插件

前言

DeepSeek Harness (DSH) 的 JSONL 会话持久化后端遵循“每个会话一个活跃写入器”的策略,本身不具备跨进程的防御机制。如果两个 dsh 服务器共享同一个 DSH_HOME(例如桌面包装器自行启动服务器,或同时运行两个 dsh web 进程),它们会使用过期的序列游标追加批次,导致会话日志损坏,报错信息通常为 corrupt session log: seq gap in committed region。

dsh-single-instance-guard 插件旨在将这种静默的损坏转化为启动时的明确失败,通过独占锁定防止并发启动。

插件概述

该插件是 DeepSeek Harness 的一个零依赖插件,由 Tang-mm95 维护,采用 MIT 许可证。它的核心作用是在启动时对 DSH_HOME 数据目录进行原子独占锁定。如果检测到另一个 dsh 服务器正在使用该目录,插件将中止启动。

核心功能

  1. 原子独占锁定:在 <DSH_HOME> 目录下创建 .dsh-server.lock 文件,文件内容包含 { pid, startedAt, hostname }。使用 O_EXCL 标志确保创建操作的原子性。
  2. 并发检测与中止:检测到冲突时,先探测锁定持有者的进程存活状态。若持有者存活,则中止当前启动并显示双语错误;若持有者已不存在,则移除锁并重试一次。
  3. 自动清理:进程退出时,仅当锁文件仍属于该进程时,自动移除锁文件。
  4. 零依赖:不依赖任何第三方库。

安装与配置

可以通过 CLI 安装,也可以手动配置。

CLI 安装

dsh plugin --profile <profile> add dsh-single-instance-guard

手动配置

在 profile 的 cordis.patch.yml 中添加以下行。必须确保该配置位于会话相关 bundles 之前:

- insert:
    - id: single-instance-guard
      name: 'dsh-single-instance-guard'

工作原理

插件首先解析 DSH_HOME(优先级为 $DSH_HOME 或 ~/.dsh)。随后尝试创建 .dsh-server.lock 文件。

  1. 成功:文件创建成功,插件持有锁。
  2. 冲突:文件已存在。插件读取文件内容并检查对应 PID 的进程是否存活。存活则报错退出;若 PID 不存在或文件格式无法解析,视为过期锁,删除后重试一次。
  3. 退出:进程结束时,检查文件中的 PID 是否仍为当前进程,是则删除锁文件。

适用场景与注意事项

该插件适用于需要确保同一 DSH_HOME 目录下只有一个 dsh 服务器运行的环境。

需要注意以下限制:
* 极小的竞态条件:当两个进程同时发现并尝试删除同一个过期锁时,存在极小的竞争窗口。但原子 O_EXCL 写入机制确保了只有一个进程能最终获取锁,另一个进程会在重试时正确失败。
* 路径保护:仅保护同一 DSH_HOME 路径下的并发服务器。对于指向同一个 session 文件但路径不同的两个 dsh 实例,插件无法保护。
* 环境要求:需要 Node.js >= 18。

总结

通过引入此插件,可以在 DSH 环境中避免因并发启动导致的会话日志损坏问题。相关源码与文档可在其 GitHub 仓库查看。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜