fix: bare clone/fetch 异步化,git 网络操作不再阻塞事件循环#267
Conversation
cloneBareAtomic / fetchIfStale 此前用 execFileSync 同步执行远程 git, clone 卡到 timeout(默认 5 分钟)期间整个单进程 bridge 的事件循环被冻死: 飞书事件无法处理与 ACK → 被飞书定时重投 → 重投又超过 5 分钟 staleness 阈值被丢弃,导致期间所有会话"毫无响应"。一次连不上远程的 clone 即可拖垮全服务。 改为 promisify(execFile) + await,让 git 在子进程执行、await 让出事件循环: - cache.ts: cloneBareAtomic / fetchIfStale / ensureBareCache 改 async, execFileSync → execFileAsync(去掉 stdio,改 maxBuffer 防输出溢出) - manager.ts: setupWorkspace 改 async(await ensureBareCache), 本地 clone / set-url / checkout 三处 git 调用一并异步化 - isolation.ts / tool.ts / registry.ts: 调用处补 await 新增回归守卫(cache.test.ts):断言 bare clone 在途时事件循环仍存活, 并发宏任务能照常推进 —— 锁死本次事故的根因(同步阻塞)。 顺带修复 identity.test.ts 的 child_process mock 缺 execFile 导致模块加载即崩。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude finished @lishuceo's task in 2m 57s —— View job Code Review — PR #267Verdict: ✅ Approve with one minor note The async refactor is correct and well-scoped. The root cause (synchronous
Other things verified:
🟡 One issue (confidence 80) — left as inline commentConcurrent cold-clone race in Testing noteThe CLAUDE.md testing policy is satisfied — async migration is covered by updated
|
PR review 反馈:ensureBareCache 异步化后,existsSync 检查与 clone 不再原子。 跨会话(不同 chat 不共享 FIFO 队列)并发请求同一未缓存仓库时,两者都会通过 existsSync(false) 后各自 clone,落败方的 renameSync 撞到已存在目录报 ENOTEMPTY, 导致该请求失败(可重试自愈,但属同步版本没有的回归)。 用 in-flight clone Promise 去重(Map<cachePath, Promise>):get→set 之间无 await, 对单线程事件循环原子,并发调用共享同一次 clone,绝不会两次 clone。 新增并发回归测试:同一未缓存仓库的两个并发 ensureBareCache 只触发一次 clone+rename。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude finished @lishuceo's task in 1m 43s —— View job Code Review — PR #267 (re-review after fix)Verdict: ✅ Approve — 1 previous issue fixed. The concurrent cold-clone race flagged in the prior review ( Fix verification — in-flight clone dedup (
|
变更概述
cloneBareAtomic/fetchIfStale用execFileSync同步执行远程 git,clone 卡到 timeout(默认 5 分钟)期间整个单进程 bridge 的事件循环被冻死 —— 飞书事件无法处理/ACK,被飞书定时重投后又超过 5 分钟 staleness 阈值被丢弃,导致期间所有会话"毫无响应"。一次连不上远程的 clone 即可拖垮全服务(线上 06-23 10:39–10:44 实测冻结 5 分钟)。promisify(execFile)+await:cache.ts的 clone/fetch/ensureBareCache全部异步化;manager.tssetupWorkspace改 async 并将本地 clone/set-url/checkout 一并异步化;isolation.ts/tool.ts/registry.ts调用处补await。execFile不支持stdio,改用maxBuffer: 64MB防输出溢出;env(GIT_LFS_SKIP_SMUDGE)保留。测试计划
npm run typecheck通过eslint(改动文件)无错vitest:1723 passed(唯一 1 个 failure 为memory/quality.test.ts,依赖DASHSCOPE_API_KEY的既有环境失败,与本改动无关)🤖 Generated with Claude Code