Repository navigation
fix(minimax-bot): 坏文件不再让插件起不来,账本写失败不再带走已经跑完的回合 - #110
MyPrototypeWhat merged 2 commits into
Conversation
读不出来的状态文件改成改名留证、从默认值起,写盘在 rename 之前先 fsync;台账写 不进去时只记一条 warn,不再把已经跑完的回合、群里后面的成员和跑完的后台报告一 并带走。版本 0.7.24。
MyPrototypeWhat
left a comment
There was a problem hiding this comment.
Approving. The recovery path keeps the unreadable bytes instead of deleting them, the flush before the rename is the right fix for the 0-byte file, and the ledger guard sits at both call sites as well as inside the store.
Verified
readJsononly quarantines on a parse failure. A read error other thanENOENTstill throws, so a permission problem is not mistaken for a corrupt file. The renamed file stays next to the original inside the plugin's data directory, and the path is built from the store's own fixed paths, not from input.writeJsonAtomicwrites and syncs the temp file before the rename. If the write or the sync fails, the temp file is removed and the error propagates, so the previousstate.jsonstays untouched. The directory sync is best effort, which is fine for Windows.- A failed ledger append is logged as
minimax_bot.usage_write_failedwith only the error code, and the turn id is not claimed, so a later write can still record it. The guards inrunBotTurnand the background job path keep the reply status, the next group member, and the job's saved status and report. - The shape checks in
init(bots,groups,schedules,sessions) reset only a field that has the wrong type. - No new reads or writes outside the data directory. The new tests live in the plugin's
tests/folder. - Version 0.7.24 matches in
package.json,.minimax-plugin/plugin.json, the MCPserverInfoand the README, above main's 0.7.21. Thecheckjob is green ate5882a3, and the branch merges cleanly.
Optional
- In
readJson, a failed rename of the corrupt file is swallowed and the defaults are returned. The nextsave()then writes overstate.json, and the evidence the README promises is gone. Consider copying the bytes to the.corrupt-file when the rename fails, or skipping the save in that case. - Quarantining a file is silent today. A
warnwith the file name when it happens would make a reset team or an empty chat explainable from the log, the same way the ledger miss is. The store already has the logger for it. .corrupt-<time>files are never cleaned up. That is fine for now, but a cap on how many are kept would stop repeated failures from piling them up.
main now carries 0.7.23 (the hand-over carries the conclusions of the round). This merge keeps that section and this branch's 0.7.24 section, and keeps the version at 0.7.24 in the three places that carry it. It also picks up the two optional points of the review: a failed rename of an unreadable file now falls back to a copy, so the bytes stay even when the name cannot change, and the quarantine says so in the log, so a team that came back empty is explainable.
|
main 上 0.7.23 合进来之后我把分支合了一次,版本仍是 0.7.24,README 里 0.7.20、0.7.21、0.7.23、0.7.24 四段按顺序各一次,没有冲突标记。用的是合并提交而不是强推,那条 APPROVED 还挂在原来那个提交上。 评审里的三条 optional 我改了两条。改名失败时现在退回复制,字节留在那里,原文件就算被下一次保存盖掉,副本还在。隔离的时候也会在日志里留一条,写着是哪个文件,这样「团队空了」或者「聊天读不出来」从日志能看出来,和账本那条一个路子。 第三条我没做。给 .corrupt 文件加个数上限是产品取舍而不是一条小修,你说现在这样也行,我就留着以后再说;要是以后重复失败把它们堆起来了,这条也好接。 门禁重跑:插件套件 394 条全过,上游 npm run check 两半也过;那两个新测试在未改的 0.7.23 上仍然是红的。 真实宿主里跑过的是改动本体,把 state.json 换成 0 字节、把 usage.jsonl 换成目录,各跑一遍。那次跑的是合并 main 之前的构建,合并之后没有再跑一遍,新增的复制兜底和那条日志也没在真实宿主里验过,这条未验证。 |
MyPrototypeWhat
left a comment
There was a problem hiding this comment.
Approving. Thanks for merging main and picking up the two notes on evidence and the log.
Verified
- The merge of main keeps the 0.7.23 hand-over work from #108.
handoverSummary/renderHandoverare in place,handover-note.test.mjsis present, and there are no conflict markers. The recovery path, the flush before the rename, and the ledger guards inrunBotTurnand the background job path are still there. - When a file cannot be parsed,
readJsonstill only quarantines on a JSON parse failure. A read error other thanENOENTstill throws. If the rename to*.corrupt-<time>fails, it copies the bytes to that name so the next save cannot erase the only copy. The copy stays next to the original, inside the plugin's data directory, and the path is built from the store's own fixed paths, not from input. - Quarantine now logs
minimax_bot.corrupt_file_quarantinedwith only the file name, so a reset team or an empty chat can be explained from the log the same way a ledger miss is. - A failed ledger append is still logged as
minimax_bot.usage_write_failedwith only the error code, and the turn id is not claimed. The reply status, the next group member, and a finished job's saved status and report are unchanged. - No new reads or writes outside the data directory. The new tests live in the plugin's
tests/folder. - Version 0.7.24 matches in
package.json,.minimax-plugin/plugin.json, the MCPserverInfoand the README, above main's 0.7.23. The README keeps the 0.7.20, 0.7.21, 0.7.23 and 0.7.24 sections, each once. Thecheckjob is green at1885cc5, and the branch merges cleanly.
Optional
- A cap on how many
.corrupt-<time>files are kept is still left for later, as noted. - The recovery tests still check that a
corruptfile is left behind after a successful rename. They do not cover a failed rename that has to copy, or assert that the quarantine warning is written.
这一版改两件事。读不出来的状态文件不再让整个插件起不来,账本写不进去也不再带走已经跑完的回合。
state.json 或任意一条聊天文件读不出来时(0 字节、写到一半被截断),Store.init 直接抛 SyntaxError,server.start 在 listen 之前就 reject,整个 Mini App 起不来,界面上什么都不出来。现在读不出来的文件改名成 *.corrupt-<时间戳> 留着不删,这次从默认值起,一个聊天文件坏就那一个聊天空,其它照常加载。成因也一起修掉,写盘原来是 writeFile 加 rename,rename 之前没有把数据刷到盘上,掉电时 rename 已经提交而数据页还没落盘,就会留下一个 0 字节的文件,现在 rename 之前先 fsync,能刷目录的地方再刷一次目录。
台账的写入是裸的 appendFile,而它挂在三个关键路径上,分别是回合的收尾、群一轮发言的循环、后台作业的收尾。磁盘满了或者 usage.jsonl 不可写的时候,已经生成的回复被判成失败、群里后面的人不再发言、跑完的后台作业的报告永久丢失。现在写入失败只记一条 warn,别的一概照旧,回复保住自己的结果,群继续往下走,后台作业照常存状态、照常投递报告。
改动很小。store.mjs 有一处读取兜底、一处写盘顺序、一处写入捕获,engine.mjs 两处调用加捕获,server.mjs 一处把日志交给 store。版本三处同改到 0.7.24,README 加了一段 0.7.24。
新增两个测试文件共七条用例,坏文件留在原地、其余聊天照常加载、形状不对的状态也能起来,以及账本写不进去时回合仍然完成、群仍然往下走、后台作业仍然投递报告。这七条在未改的 0.7.21 上全是红的。插件自带套件 386 条全过,上游 npm run check 两半也过。
另外改了 tests/unknown-zombie.test.mjs 的收尾。那个用例在 dispose 之后直接删数据目录,而被中止的回合还会补一次写盘,删除和写盘撞上了,清理报 ENOTEMPTY。收尾改成先等引擎停下来、等写链排空,再删目录,和同文件里另一个用例以及服务端的关闭流程一个写法,断言一个字没动。
真实产品里跑过两种故障。把 state.json 换成 0 字节后重启,插件照常起来,坏文件留在原地,之前的聊天文件没被牵连。把 usage.jsonl 换成目录后连发四条消息,账本每一条都写不进去,四条里三条照常回复,另一条模型那一层没产出,宿主会话 0 条消息,同样条件下再发就正常,这条没有复现,仅个人判断它不在这个改动里,也没有写进代码。
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.