diff --git a/packages/adapters/src/fs/fsworker.ts b/packages/adapters/src/fs/fsworker.ts index 0a94c210..b6e9017d 100644 --- a/packages/adapters/src/fs/fsworker.ts +++ b/packages/adapters/src/fs/fsworker.ts @@ -1,5 +1,5 @@ // fsproxy 执行子进程:从 stdin 读一条 JSON 请求,执行单个文件操作,stdout 逐行 JSON 上报 -// {t:"hb",phase,bytes,total}(按 progressIntervalMs 节流,阶段切换立即报)/ {t:"ok",result} / {t:"err",code,message}。 +// {t:"hb",phase,bytes,total}(按 progressIntervalMs 节流,阶段切换与阶段完成立即报)/ {t:"ok",result} / {t:"err",code,message}。 // SIGTERM → 中止当前操作(copy 会清掉自己的 partial)后退出;挂死在系统调用里时由父进程 SIGKILL 回收。 // 只依赖 node 内置模块,`deno run --no-config` 毫秒级启动。编译二进制可在入口按 --role fsworker 调 fsWorkerMain()。 import { toFsError } from "./errors.ts"; @@ -35,7 +35,14 @@ export async function fsWorkerMain(progressIntervalMs = Number(Deno.env.get("UMT const progress = (p: FsProgress) => { const hang = req._test?.hangAfterBytes; const now = Date.now(); - if (p.phase !== lastPhase || now - lastAt >= progressIntervalMs || (hang !== undefined && p.bytes >= hang)) { + // 阶段切换、阶段完成(bytes 到 total)立即报,其余按间隔节流——否则最后一跳可能被节流吞掉 + const phaseDone = p.total > 0 && p.bytes >= p.total; + if ( + p.phase !== lastPhase || + phaseDone || + now - lastAt >= progressIntervalMs || + (hang !== undefined && p.bytes >= hang) + ) { lastAt = now; lastPhase = p.phase; send({ t: "hb", ...p });