fix(oknte): 配置还原不再停在半删状态 - #617
Open
qiyinxi wants to merge 1 commit into
Open
Conversation
_restore_script_config_from_temp 等四处都是同一序列: rmtree(dst, ignore_errors=True) 之后 tmp.rename(dst)。ok-nte 进程若仍持有 configs 下任一文件的句柄,rmtree 会删掉能删的、留下被占用的,然后不报错返回; dst 因此仍然存在,下一行往一个已存在的目录 rename 在 Windows 上必然 WinError 5。 结果是用户配置目录半删、备份留在 .tmp 里没还原回去。 新增 tools/config_swap.replace_config_dir 统一这四处: - 删除 dst 带短重试,等 ok-nte 刚被结束后句柄释放 - 删不干净时不再 rename,改为把备份就地覆盖回 dst,把 rmtree 已删掉的部分补回来 - 不再用 ignore_errors=True 掩盖删除失败 Closes AUTO-MAS-Project#535 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
审查者指南新增统一的异步配置目录替换工具,通过删除重试和删除失败时就地覆盖,解决 Windows 句柄占用造成的配置目录半删问题,并将 OK-NTE 中四处重复实现迁移到该工具。 具备容错能力的 OK-NTE 配置替换时序图sequenceDiagram
participant Caller as OKNTE_Task
participant Swap as replace_config_dir
participant FS as Windows_FileSystem
participant Process as OKNTE_Process
Caller->>Swap: replace_config_dir(src, dst)
Swap->>FS: copytree(src, dst.tmp, dirs_exist_ok=True)
loop up to retries
Swap->>FS: rmtree(dst)
alt destination removed
FS-->>Swap: success
else destination locked
FS-->>Swap: OSError
Swap->>Swap: asyncio.sleep(delay)
end
end
alt dst removed
Swap->>FS: rename(dst.tmp, dst)
else dst remains locked
Swap->>FS: copytree(dst.tmp, dst, dirs_exist_ok=True)
Swap->>FS: rmtree(dst.tmp)
end
Swap-->>Caller: replacement complete
文件级变更
可能关联的问题
提示和命令与 Sourcery 交互
自定义你的使用体验访问你的控制面板以:
获取帮助Original review guide in EnglishReviewer's Guide新增统一的异步配置目录替换工具,通过删除重试和删除失败时就地覆盖,解决 Windows 句柄占用造成的配置目录半删问题,并将 OK-NTE 中四处重复实现迁移到该工具。 Sequence diagram for resilient OK-NTE configuration replacementsequenceDiagram
participant Caller as OKNTE_Task
participant Swap as replace_config_dir
participant FS as Windows_FileSystem
participant Process as OKNTE_Process
Caller->>Swap: replace_config_dir(src, dst)
Swap->>FS: copytree(src, dst.tmp, dirs_exist_ok=True)
loop up to retries
Swap->>FS: rmtree(dst)
alt destination removed
FS-->>Swap: success
else destination locked
FS-->>Swap: OSError
Swap->>Swap: asyncio.sleep(delay)
end
end
alt dst removed
Swap->>FS: rename(dst.tmp, dst)
else dst remains locked
Swap->>FS: copytree(dst.tmp, dst, dirs_exist_ok=True)
Swap->>FS: rmtree(dst.tmp)
end
Swap-->>Caller: replacement complete
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #535
问题
PermissionError: [WinError 5] ... 'working/configs.tmp' -> 'working/configs'(SentryAUTO-MAS-BACKEND-4H)。OK-NTE 里有 4 处完全相同的序列:
ok-nte 进程若仍持有
configs下任一文件的句柄,第三行会删掉能删的、留下被占用的,然后不报错返回;dst因此仍然存在,第四行往一个已存在的目录rename,在 Windows 上必然失败。结果是用户的配置目录停在半删状态,备份留在
.tmp里没有还原回去——属于会丢用户数据的路径。改动
新增
app/task/OkNte/tools/config_swap.py,用replace_config_dir(src, dst)统一这 4 处:dst带短重试(默认 5 次 × 0.5s),等 ok-nte 刚被结束后 Windows 释放句柄——manager.final_task里的还原紧跟在子任务 kill 之后,这个竞态是主因;copytree(dirs_exist_ok=True)就地覆盖回dst,把前面rmtree已经删掉的部分补回来。宁可留下几个多余文件,也不让配置停在半删状态;ignore_errors=True掩盖删除失败,删不掉会写一条 warning 说明原因。替换的 4 处:
manager.py_restore_script_config_from_temp、AutoProxy.pyset_oknte、ScriptConfig.py载入 GUI 配置与final_task。与 #456 的关系
#456 开着,改的是同一片代码,但解的是另一个根因:它用
force_rmtree清只读属性,并把还原包进 try/except。只读属性和句柄占用是两回事——force_rmtree解不了被打开的文件,占用时rmtree照样半删、rename照样 WinError 5(#456 的 try/except 会让它不再中断任务,但配置仍停在半删状态)。两者可以叠加,合并时会有冲突。建议先合本 PR:它把这 4 处收敛成一个函数,#456 的
force_rmtree之后只要改config_swap.py一处即可。如果你们更愿意先合 #456,我来跟着改。本地验证
另外在本地写了三条针对
replace_config_dir的测试并跑过(按tests/AGENTS.md,bug 边界测试不提交):.tmp不残留dst没有半删、备份内容确实还原回去、.tmp不残留dst本就不存在3 passed in 8.97s。第二条是这个 bug 的核心场景,在 Windows 上用open(file, "rb")持有句柄复现的。没有做真机手测:需要装 ok-nte 并让它在还原时刚好没退干净,本地没有环境。
请审阅
@Jungle178 OK-NTE 专项是你写的,请你看看「删不掉就就地覆盖」这个取舍是否可接受——它的代价是多余文件可能残留一轮。确认后请你自行合并,我不代合。
Sourcery 摘要
使 OK-NTE 配置恢复能够抵御 Windows 文件句柄竞争问题,并避免目录处于部分删除状态。
错误修复:
增强功能:
Original summary in English
Summary by Sourcery
Make OK-NTE configuration restoration resilient to Windows file-handle races and avoid leaving directories in a partially deleted state.
Bug Fixes:
Enhancements: