Skip to content

(Codex) 修复 packages/filesystem 中认证恢复与删除幂等问题#1375

Merged
CodFrm merged 2 commits intomainfrom
fix/sync/002
Apr 27, 2026
Merged

(Codex) 修复 packages/filesystem 中认证恢复与删除幂等问题#1375
CodFrm merged 2 commits intomainfrom
fix/sync/002

Conversation

@cyfung1031
Copy link
Copy Markdown
Collaborator

背景

云同步场景下,packages/filesystem 这层直接决定了“认证失效后是否能恢复”和“多设备重复删除是否会被误判成失败”。

这次修正聚焦两类高风险问题:

  1. 认证已失效时,底层仍可能继续返回旧 token,导致后续请求反复 401/403
  2. 文件已被其他设备删除时,重复删除会被当作异常,影响同步收敛

本次修改只处理高价值、低歧义、可验证的问题,不扩大到更大范围的重构。


修正重点

1. 修复 AuthVerify() 在 token 过期后错误回退旧 token 的问题

修改文件

  • packages/filesystem/auth.ts

问题

  • 旧逻辑中,token 已过期时如果 refresh 失败,会继续返回旧 token
  • 这会让调用方误以为认证仍然有效,后续请求持续失败但根因被隐藏

修正

  • 当 token 已过期或已被判定失效时,refresh 失败直接抛错
  • 不再回退到旧 token

意义

  • 避免“认证已经坏了,但系统还继续拿旧 token 硬跑”
  • 让上层更早感知真实认证问题,而不是进入反复失败状态

2. 修复 OneDrive 请求层在 token 刷新后返回旧失败结果的问题

修改文件

  • packages/filesystem/onedrive/onedrive.ts

问题

  • OneDrive request() 在检测到 token 失效后会刷新 token 并重试
  • 但原逻辑在重试成功后,返回的仍可能是第一次失败结果,而不是第二次成功结果
  • 同时,nothen 原始响应路径不支持 token 刷新恢复

修正

  • 统一抽出 token 刷新后的重试逻辑
  • 刷新成功后返回重试结果,而不是旧失败结果
  • nothen 路径也支持 401 后刷新并重试
  • 补上基于 HTTP 状态的错误处理

意义

  • 避免“认证已恢复,但调用方仍收到失败结果”
  • 提高 OneDrive 在 token 过期场景下的自恢复能力

3. 为 Google Drive 请求层补充更稳定的认证恢复与 HTTP 错误处理

修改文件

  • packages/filesystem/googledrive/googledrive.ts

问题

  • 原逻辑默认直接解析 JSON,HTTP 层错误不够明确
  • nothen 原始响应路径缺少 token 自动恢复
  • 删除缺失文件时会直接报错

修正

  • 统一先检查 HTTP 状态,再解析响应
  • 401 时刷新 token 后重试
  • nothen 路径支持 token 自动恢复
  • delete() 对“目标不存在”改为幂等成功

意义

  • 减少 HTTP 错误被包装成 JSON 解析异常
  • 提高认证恢复一致性
  • 让多设备重复删除符合幂等语义

4. 为 Dropbox 请求层补充 token 恢复,并将删除改为幂等

修改文件

  • packages/filesystem/dropbox/dropbox.ts

问题

  • 原始响应路径在 token 过期后无法自动恢复
  • 删除不存在文件时会抛错
  • 请求头使用 append(),重复设置时可读性较差

修正

  • nothen 路径支持 401 后刷新 token 并重试
  • 正常请求也统一支持 token 自动恢复
  • delete()path_lookup/not_found / path/not_found 视为成功
  • 将 Authorization 设置改为 set()

意义

  • 提高 Dropbox 认证恢复能力
  • 避免多设备重复删除时产生假失败
  • 让请求头设置语义更明确

5. 为 WebDAV 删除补充幂等语义

修改文件

  • packages/filesystem/webdav/webdav.ts

问题

  • 删除一个已经不存在的文件会抛错
  • 在云同步、多设备收敛场景下,这不应该算异常

修正

  • delete() 遇到 404 时静默成功

意义

  • 让 WebDAV 删除语义和同步场景更匹配
  • 避免“文件其实已经删掉,但同步却被记成失败”

6. 为 OneDrive 删除补充幂等语义

修改文件

  • packages/filesystem/onedrive/onedrive.ts

修正

  • delete() 遇到 404 时静默成功

意义

  • 和其他云盘保持一致
  • 避免重复删除误报异常

测试

新增测试

  • packages/filesystem/auth.test.ts
  • packages/filesystem/onedrive/onedrive.test.ts
  • packages/filesystem/googledrive/googledrive.test.ts
  • packages/filesystem/dropbox/dropbox.test.ts

补充测试

  • packages/filesystem/webdav/webdav.test.ts

覆盖内容

  • token 过期时 refresh 失败不再回退旧 token
  • OneDrive 刷新 token 后返回真正的重试结果
  • Google Drive / Dropbox / OneDrive / WebDAV 删除不存在文件时保持幂等成功

验证结果

  • 相关 vitest 测试通过
  • tsc --noEmit 通过

影响范围

本次改动主要影响:

  • token 过期/失效后的恢复路径
  • 删除不存在文件时的行为
  • OneDrive / Google Drive / Dropbox 的请求层错误处理一致性

不影响:

  • 文件内容格式
  • 上层同步协议
  • 现有 packages/filesystem 公开接口签名

总结

这次修正的核心不是增加新能力,而是修正两类会放大同步问题的底层误判:

  • 认证已失效,却继续返回旧 token
  • 文件已不存在,却把重复删除当成错误

修完后,packages/filesystem 在以下场景下会更稳定:

  • token 过期
  • 网络波动
  • 多设备重复删除
  • 同步收敛过程中出现“目标已不存在”的正常状态

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 聚焦修复 packages/filesystem 在云同步场景下的两个关键稳定性问题:认证失效后的错误 token 回退/恢复,以及多设备重复删除导致的非幂等失败;并补齐对应的单测覆盖。

Changes:

  • 修复 AuthVerify():token 过期/失效时 refresh 失败不再回退旧 token,而是直接抛错暴露真实认证问题。
  • 统一增强 OneDrive / Google Drive / Dropbox 的 request 认证恢复逻辑(401 自动刷新并重试),并让删除在目标不存在时幂等成功(404 / not_found 视为成功)。
  • 新增/补充 Vitest 用例覆盖 token 刷新与幂等删除行为。

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/filesystem/auth.ts token 过期/失效时 refresh 失败改为抛错,避免回退旧 token 掩盖认证问题
packages/filesystem/auth.test.ts 新增 AuthVerify 的“过期 refresh 失败不回退”与“未过期不刷新”测试
packages/filesystem/onedrive/onedrive.ts request 支持 401 刷新并返回重试结果;delete 对 404 幂等成功
packages/filesystem/onedrive/onedrive.test.ts 新增 OneDrive request 刷新后返回重试结果、delete 404 幂等测试
packages/filesystem/googledrive/googledrive.ts request 统一先按 HTTP 状态处理并支持 401 刷新;delete 对缺失/404 幂等
packages/filesystem/googledrive/googledrive.test.ts 新增 GoogleDrive delete 幂等(fileId 缺失 / 404)测试
packages/filesystem/dropbox/dropbox.ts request 增加 401 刷新重试;delete 对 not_found 幂等成功;header 用 set()
packages/filesystem/dropbox/dropbox.test.ts 新增 Dropbox delete not_found 幂等测试
packages/filesystem/webdav/webdav.ts WebDAV delete 对 404 幂等成功
packages/filesystem/webdav/webdav.test.ts 补充 WebDAV delete 404 幂等测试
Comments suppressed due to low confidence (1)

packages/filesystem/onedrive/onedrive.ts:145

  • delete() 的返回类型是 Promise,但最后 return resp; 实际返回了值(且 resp 在此处也不会被调用方使用)。建议改为直接 return;/移除该 return 表达式,避免误导调用方并让实现与签名一致。
    if (resp.status !== 204) {
      throw new Error(await resp.text());
    }
    return resp;
  }

Comment on lines +9 to +12
beforeEach(async () => {
vi.clearAllMocks();
await chrome.storage.local.clear();
});
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里用 vi.stubGlobal("fetch", ...) 覆盖了全局 fetch,但没有在用例结束后恢复,可能导致其它测试用例受到污染(同仓库里如 packages/filesystem/s3/client.test.ts 会在 afterEach 里 vi.unstubAllGlobals)。建议在本 describe 增加 afterEach 调用 vi.unstubAllGlobals()(或保存原 fetch 并恢复),确保测试隔离。

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +22
beforeEach(async () => {
vi.clearAllMocks();
await chrome.storage.local.clear();
});
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

该文件通过 vi.stubGlobal("fetch", fetchMock) 注入全局 fetch,但没有在用例结束后 unstub,可能污染同一测试进程中的其他 suite。建议补充 afterEach(() => vi.unstubAllGlobals())(或在 beforeEach 里先 unstub)来保证测试隔离。

Copilot uses AI. Check for mistakes.
- auth.test.ts / onedrive.test.ts 增加 afterEach 恢复原 fetch,
  避免 stubGlobal("fetch") 泄漏到其它测试套件。
- 不使用 vi.unstubAllGlobals():会连带移除 setup 中注入的全局
  chrome mock,导致后续用例 chrome 未定义。
- onedrive.delete() 移除多余的 return resp;,与 Promise<void> 签名一致。
@CodFrm CodFrm merged commit a1eb8dc into main Apr 27, 2026
2 of 3 checks passed
@CodFrm CodFrm deleted the fix/sync/002 branch April 27, 2026 06:07
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.

3 participants