Skip to content

Conversation

@mkitsdts
Copy link
Contributor

@mkitsdts mkitsdts commented Jan 24, 2026

Description / 描述

添加额外的错误检查,修复 issue #1946 #2002

Motivation and Context / 背景

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

创建目录需要一定时间,这段时间内无法获取创建目录的结果,可能重复发送创建目录请求。而后续代码没有跳过重复创建目录的错误,直接结束运行,所以出现这个问题。

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错误。

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.

2 participants