Skip to content

Conversation

@mkitsdts
Copy link
Contributor

@mkitsdts mkitsdts commented Jan 24, 2026

Description / 描述

添加额外的错误检查。

在原来Webdav的Put函数里,可能会调用Rename函数做禁止覆盖上传,原来的逻辑是Rename返回任何错误都将直接结束请求。但如果是同名文件已经存在,则不需要rename可以继续执行,因为openlist_to_delete后缀的区别度足够大,一般用户不会创建 openlist_to_delete 后缀的文件

创建目录 /a/b 和 /a/c ,会并发执行 Get(a)。因为缓存更新是非原子性的,所以存在缓存丢失可能。缓存丢失导致后续再次调用 Get 函数时无法读取到缓存的内容,继而执行 list 函数
list函数可能会因为网盘后端存在缓存和数据库短暂不一致,从而出现无法获取目录内容的情况。理论概率很低,但实测并发量大的时候,存在极少部分文件发生重名冲突
解决方案是添加额外的错误检查,忽略Makedir函数报的重复创建目录错误

Motivation and Context / 背景

Close #1946
Close #2002

How Has This Been Tested? / 测试

在不同存储之间来回复制嵌套文件夹,测试无问题

Checklist / 检查清单

  • I have read the CONTRIBUTING document.
    我已阅读 CONTRIBUTING 文档。
  • I have formatted my code with go fmt or prettier.
    我已使用 go fmtprettier 格式化提交的代码。
  • I have added appropriate labels to this PR (or mentioned needed labels in the description if lacking permissions).
    我已为此 PR 添加了适当的标签(如无权限或需要的标签不存在,请在描述中说明,管理员将后续处理)。
  • I have requested review from relevant code authors using the "Request review" feature when applicable.
    我已在适当情况下使用"Request review"功能请求相关代码作者进行审查。
  • I have updated the repository accordingly (If it’s needed).
    我已相应更新了相关仓库(若适用)。

@mkitsdts mkitsdts changed the title Op fs makedir fix(internal/fs):add error check Jan 24, 2026
@KirCute
Copy link
Member

KirCute commented Jan 24, 2026

我翻了一下op.MakeDir的实现,op.MakeDir是先Get,如果返回的objdir就直接跳过,按理来说不会出现重复创建文件夹报错的问题,我觉得应该重新评估一下这两个 issue 的出现原因。

MakeDir唯一一种返回object already exists的情况是在op/fs.go#L319,也就是Get返回的err为nil,并且返回的obj不是dir时,而且返回的不是errs.ObjectAlreadyExists而是原地New出来的一个错误。

@mkitsdts
Copy link
Contributor Author

我翻了一下op.MakeDir的实现,op.MakeDir是先Get,如果返回的objdir就直接跳过,按理来说不会出现重复创建文件夹报错的问题,我觉得应该重新评估一下这两个 issue 的出现原因。

MakeDir唯一一种返回object already exists的情况是在op/fs.go#L319,也就是Get返回的err为nil,并且返回的obj不是dir时,而且返回的不是errs.ObjectAlreadyExists而是原地New出来的一个错误。

先Get,没有获取到obj,然后Makedir,在Makedir完成前,后面并发执行的任务也可能Get,没有获取到obj,又调用Makedir。

errs.IsObjectAlreadyExists是具体实现的驱动返回的。

不过同一文件夹下文件夹和文件不能同名这里确实有点问题,部分网盘允许同名,但部分网盘不允许同名。再斟酌一下。

@mkitsdts
Copy link
Contributor Author

我测试了主流的几个网盘,百度,夸克,天翼,还有UC。在同一个文件夹下,已经存在test文件的情况下,创建test文件夹都不会报错

其中UC和夸克允许同名文件和文件夹共存,百度、天翼会对test文件夹进行改名

仍然有潜在bug

@KirCute
Copy link
Member

KirCute commented Jan 24, 2026

先Get,没有获取到obj,然后Makedir,在Makedir完成前,后面并发执行的任务也可能Get,没有获取到obj,又调用Makedir。

我说的先GetMakeDir是套在mkdirG.Do里的,应该不会出现这种并发问题

@KirCute
Copy link
Member

KirCute commented Jan 24, 2026

我测试了主流的几个网盘,百度,夸克,天翼,还有UC。在同一个文件夹下,已经存在test文件的情况下,创建test文件夹都不会报错

其中UC和夸克允许同名文件和文件夹共存,百度、天翼会对test文件夹进行改名

仍然有潜在bug

你是你用你这个分支测的还是用base测的

@mkitsdts
Copy link
Contributor Author

你是你用你这个分支测的还是用base测的

测试是直接在网盘客户端测的。通过检查各家网盘的后端系统是否允许同一文件夹下出现文件夹和文件同名,判断是否需要考虑dstPath同名的是文件还是文件夹这个问题

@mkitsdts
Copy link
Contributor Author

我说的先GetMakeDir是套在mkdirG.Do里的,应该不会出现这种并发问题

base分支的测试结果:

多次从local存储复制一个大型文件夹到uc网盘,每次都会存在部分文件复制失败,且这些文件每次都不相同。根据日志记录,makedir调用后出现了同名错误。重试任务后均成功。

修改后的分支测试结果:

多次从local存储复制一个大型文件夹到uc网盘,复制都成功,不会出现复制失败

@mkitsdts
Copy link
Contributor Author

mkitsdts commented Jan 24, 2026

我测试了singleflight,测试方法是在do函数调用doCall前打印当前的key,检查是否存在重复key
测试结果是,多个key重复打印

初步判断:
mkdirG会在传递的函数调用完成后删除key,导致后续的key重复执行

但按理不应该出现这种情况,还需要再探究一下。既然出现了,说明Get返回了objectnotfound错误。

@xrgzs xrgzs changed the title fix(internal/fs):add error check fix(internal/fs): add error check Jan 29, 2026
@jyxjjj
Copy link
Member

jyxjjj commented Jan 30, 2026

@mkitsdts Sorry for the interruption, I've invited you to join our team.

@xrgzs xrgzs changed the title fix(internal/fs): add error check fix(internal/fs): add ObjectAlreadyExists error check Jan 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] 为啥会有这么多同名冲突 [BUG] 天翼云盘上传部分文件会出现Method not allowed的错误

4 participants