Repository navigation
Replies: 8 comments
|
机制链条你基本说对了,但有个前提是错的,而且它决定了这条报告该怎么写:shipped 的 web 档位根本不挂这个工具——你现在是有意打开了一个可选 bundle,不是撞上了官方默认配置。 先说这个前提
web: { bundles: ['@deepseek-ai/dsh-base', '@deepseek-ai/dsh-web-app'] },而
你引的那段 所以你在 我顺手也核了版本: 你说对的部分单事务 + 末尾提交 + abort 回滚 +
超时常量也对: 有一处要修正你建议的"改成 你另外那个判断是对的:只改 上游可以提的方向一个是把对账拆成按会话增量提交,而不是所有写操作挤在同一个 边界我核的是 |
|
感谢 @PerryLink 的逐行核对,两处更正都收下了,正文已同步修订(TL;DR 与证据 1 的定性表述、上游建议 #3,文末新增「更正」一节)。 本地考证补充,供后续遇到同类现象的读者定位:
接下来本地按确认过的缓解路径执行: |
|
Mitigation result: persistent index + raised You wrote that you would apply Environment: official Before the change, every Two configuration changes only:
After a restart, wall times taken from the session log (tool-call event → tool-result event):
So the loop is broken: the first reconcile now runs to completion and commits, instead of being aborted and rolled back. Three caveats worth keeping next to the mitigation:
|
|
缓解已在本机 rc.2 落地并验证,补充数据点(与 @dust617 的 alpha.3 结果互为印证): 配置(用户层 - id: optional-session-query-sqlite
name: '@deepseek-ai/dsh-session-query-sqlite'
config:
path: !!js dshHomePath('storages/session-search.sqlite')
openAt: first-search
- id: optional-tool-session-query
name: '@deepseek-ai/dsh-tool-session-query'
config:
searchTimeoutMs: 600000验证(0.2.1-rc.2,459 会话 / 约 190MB zstd / Windows 11 x64 / Node v24.18.0,含大量 pre-v4 老格式会话):
rc.2 现状: |
|
后续数据点:持久化索引 + 放宽
本机量化:459 个会话中 196 个是 pre-v4(147 个在主工作区,最早到 2026-08),增量搜索稳定约 90s,且随历史会话累积线性变贵。 因此"每次都慢"的根治在上游,两个不改变默认行为的收敛方向:
在官方收敛之前,本机的缓解(持久化索引 + 大超时)至少把"永久死锁"降级为"每次分钟级",晚间批处理场景可用;交互式高频搜索仍不实用。 |
|
这份数据点很有用,尤其是「无需重启」和「增量 91s 反而比 dust617 的 39s 更慢」这两条 —— 后者正好把「慢」的原因从「配置没调对」推到「pre-v4 占比」。我把你引的三处 README 逐条对了一遍,全部成立,另外补两个你没提的锚点。 README 原文(
所以你归纳的三件事(只读不发布 successor / 对账是纯读 / fingerprint 覆盖整个持久化根)是逐字有据的,不是推断。 另外两个支持你判断的锚点
你提的两个收敛方向,我的取舍 方向一(对账改走 write-open 发布 successor)确实能一次性消掉重复成本,但代价要说清楚:对账是只读操作,一旦它会写盘,任何一次搜索都可能对用户的会话目录产生 方向二( 关于 我核了,rc.2 里确实有: 最后提醒一句:你现在的缓解(持久化 + 600s 超时)把「永久死锁」降成「分钟级」,但如果 corpus fingerprint 是全局失效的,那么任何新会话的任何写入都会让下一次搜索重付全额 —— 这意味着一台白天在用的机器上,这个成本不是每小时一次,而是接近每次。你报告里那句「随历史会话累积线性变贵」可以再准确一点:它首先是被写入频率驱动的。 |
|
感谢逐条核对与两个补充锚点, 写入频率这一点接受修正:本机是白天高频使用的机器,"每次搜索都重付全额"的描述比"线性变贵"更准确——昨天两次调用间隔约三分钟,期间有新会话写入,91s 的增量成本与该模型吻合。 方向一收回,同意它不是性能补丁而是语义变更;方向二( |
|
按方向二的精神本地先跑通了:写了一个独立脚本直接组合
如果官方后续落地 |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
English TL;DR
In my deployment, the
session_searchtool comes from the opt-in experimental bundle@deepseek-ai/dsh-experimental-session-search(enabled via the plugin manager — not part of any shipped template, see the correction note at the bottom), backed by@deepseek-ai/dsh-session-query-sqliteconfigured withpath: ':memory:'andopenAt: first-search. Before every search, the backend reconciles the entire persisted corpus into the in-memory FTS5 index and commits in a single transaction at the end, while the tool enforces a 30 s budget (searchTimeoutMs, default3e4) whose abort signal propagates into the backend (SESSION_QUERY_ABORTED), rolling that transaction back. Once the session corpus grows past what one reconcile can process within 30 s, every search starts from an empty in-memory index, times out, rolls back, and makes zero progress — a permanent, deterministic timeout loop. Restarts cannot help (:memory:), anderr.logstays clean because the abort is a typed, handled error, not a crash.环境 / Environment
0.2.1-alpha.2,profileweb,Windows 11 x64,Nodev24.18.0session_search扫描当日会话现象 / Symptoms
session_search调用一律 30 秒整超时:tool call timed out after 30000ms,与查询词、时段无关session_event_search在大会话上同样超时err.log保持 0 字节(策略性中止,非崩溃)~/.dsh/sessions下 9 个工作区目录、约 459 个会话 zstd 文件、约 190 MB 压缩(最大的单一工作区 379 会话 / 158 MB,其中 104 个是近 7 天新增)排查证据 / Evidence (0.2.1-alpha.2)
组合配置
~/.dsh/profiles/web/cordis.yml(boot 后实际生效):L103-107 基础挂载:
dsh-session-query-sqlite,path: ':memory:',openAt: neverL1412-1420 工具实际使用的
optional-session-search组(isolate: { sessionQuery: true }):该组内容来自
@deepseek-ai/dsh-experimental-session-search/cordis.patch.yml。注意:这是一个 shipped 模板默认不含的可选 bundle(base/web-app 的 shipped 挂载均为openAt: never,搜索禁用),本机出现这组配置是因为我在插件管理器中启用了它——原报告此处定性有误,已在文末「更正」一节说明。全盘
~/.dsh下无任何*.db文件,佐证索引从未落盘(:memory:的直接后果)。工具超时默认 30000ms:
dsh-tool-session-query/lib/index.js中searchTimeoutMs: z.number()...default(DEFAULT_SEARCH_TIMEOUT_MS)、const searchTimeoutMs = config.searchTimeoutMs ?? 3e4;执行时把exec.signal传入searchSessions(..., { signal })。后端中止与事务路径:
dsh-session-query-sqlite/lib/index.js中对账以BEGIN IMMEDIATE开单事务、结束时一次性提交;isAbort(error) || signal?.aborted时抛SESSION_QUERY_ABORTED→ 事务回滚,已建内容全部丢弃。语料规模见上 → 单次全量对账(解压 zstd + 语义抽取 + FTS5 写入)远超 30 秒。
死锁机制 / The deadlock
每次搜索的执行顺序是:先把全语料冷建进内存索引(单事务、最后提交)→ 执行查询。而工具预算只有 30 秒,超时中止信号直达后端,事务回滚。语料一旦越过"单次对账能在 30 秒内完成"的阈值,之后每次尝试都是:空索引 → 从零冷建 → 30 秒打断 → 回滚 → 下次依旧空索引。没有任何自愈路径:
:memory:让重启也帮不上忙(重启反而保证从空开始),协作式取消让进度永远无法累积。10-13 起所有调用超时(含 10-13 / 10-14 多次定时任务内超时与一次手动复现)。至于是"语料增长越过 30 秒冷建阈值"还是"该实验 bundle 恰在此窗口内被启用、启用即坏",两种发病路径都成立、无法定论,见文末「更正」。
修复建议 / Suggestions
用户侧临时缓解(思路验证,未实施):patch 用户层把
optional-session-query-sqlite.path指到真实文件 +optional-tool-session-query.searchTimeoutMs调大(如 600000)。两处需同改——只改 path 不够,首次冷建仍会撞 30 秒预算回滚;冷建成功一次后转为增量,恢复正常。上游可考虑的方向:
:memory:;openAt配成startup今天做不到——startup 路径只调用_ensureReady打开数据库,_reconcile仍在每次搜索调用内携带调用方 signal 执行,需要代码级解耦);SESSION_QUERY_RECONCILE_INCOMPLETE)而非裸的工具超时,便于代理与用户诊断。附
如需更多现场数据(配置原文、目录清单、时间线、复现脚本),随时可以提供。本文所有路径以
~/.dsh相对形式给出,无敏感信息。更正 / Correction(2026-10-15,据 @PerryLink 的源码级核对修订)
session_search不在任何 shipped 模板里。web 档位只挂@deepseek-ai/dsh-base+@deepseek-ai/dsh-web-app,两者的session-query-sqlite均为openAt: never(搜索禁用)。本文引用的:memory:+first-search配置属于可选 bundle@deepseek-ai/dsh-experimental-session-search(OPTIONAL_BUNDLES成员,"offered switched off by the plugin manager"),是我在插件管理器中自行启用的(本机 profiledsh.profile.bundles可证)。原报告"这是官方默认行为、不是用户改坏的"的表述撤回:这不是官方默认问题,而是 opt-in 实验插件在大语料机器上的表现。openAt改为startup今天无法把对账移出 30 秒预算——startup 只保证打开数据库(_ensureReady),_reconcile仍在每次搜索调用内携带调用方 signal 执行。真正的后台建索引需要代码级解耦。:memory:的死锁组合;DEFAULT_SEARCH_TIMEOUT_MS = 30_000;signal 一路贯通到后端;"只改path不够、必须与searchTimeoutMs同调放大,成功提交一次后经 revision 比对转增量"的缓解路径。All reactions