Skip to content

fix: push/pull 网络请求添加超时和重试机制#29

Open
cunoe wants to merge 1 commit intomainfrom
fix/issue-14-timeout-retry
Open

fix: push/pull 网络请求添加超时和重试机制#29
cunoe wants to merge 1 commit intomainfrom
fix/issue-14-timeout-retry

Conversation

@cunoe
Copy link
Copy Markdown
Contributor

@cunoe cunoe commented Apr 1, 2026

Summary

  • 新建 src/utils/http.ts,封装 fetchWithRetry 工具函数
  • 使用 AbortController 实现 30s 请求超时
  • 对 5xx 错误和网络故障进行指数退避重试(最多 3 次,延迟 1s/2s/4s)
  • 替换 push.ts 和 pull.ts 中的裸 fetch 调用,verbose 模式下显示重试日志

Closes #14

Test plan

  • envx push 正常推送仍然工作
  • envx pull 正常拉取仍然工作
  • 模拟网络超时场景验证 30s 超时生效
  • 模拟 5xx 错误验证重试逻辑和指数退避

)

- Create shared fetchWithRetry utility with 30s AbortController timeout
- Add exponential backoff retry for 5xx errors and network failures (max 3 retries)
- Replace raw fetch calls in push.ts and pull.ts with fetchWithRetry
Copy link
Copy Markdown

@leaperone-bot leaperone-bot left a comment

Choose a reason for hiding this comment

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

🤖 Code Review 🟢

总体评价

这是一个干净的重构 PR,将 push.tspull.ts 中重复的 fetch 逻辑抽取到 src/utils/http.tsfetchWithRetry 工具函数中,同时增加了超时(30s)和指数退避重试(最多 3 次)机制。代码结构合理,逻辑清晰,减少了约 47 行重复代码。

优点

  1. 良好的关注点分离:将网络请求逻辑从命令文件中解耦,集中到 http.ts 工具模块
  2. 合理的默认值:30s 超时、最多 3 次重试、指数退避(1s/2s/4s)都是合理的生产配置
  3. 正确的重试策略:仅对 5xx 和网络错误重试,不会对 4xx 等客户端错误重试
  4. AbortController 超时实现:使用标准 API 实现超时,无需外部依赖
  5. verbose 模式集成:重试日志仅在 verbose 模式下输出,不影响正常使用体验

小建议(非阻塞)

  1. clearTimeout 在 catch 中的位置:当前实现是正确的,catch 中也调用了 clearTimeout(timer),确保了定时器清理。不过可以考虑用 try/finally 模式来更明确地保证清理:

    try {
      const response = await fetchFn(url, { ... });
      // handle response
    } catch (error) {
      // handle error
    } finally {
      clearTimeout(timer);
    }
  2. 5xx 最后一次重试后的响应处理:当最后一次重试返回 5xx 时,代码会正确返回该 response(因为 attempt < maxRetries 为 false,不进入重试分支),这是合理的设计——让调用方决定如何处理。建议在 verbose 模式下对这种情况也输出一条日志说明已耗尽重试次数。

  3. isNetworkError 的判断:仅通过 error instanceof TypeError 判断网络错误在大多数场景下可行(fetch 规范中网络错误确实抛出 TypeError),但如果用户手动 abort 了请求或存在其他 TypeError 来源,可能会误判。目前场景下问题不大,仅作备注。

  4. 测试覆盖:项目目前没有单元测试,fetchWithRetry 作为纯工具函数非常适合作为第一个测试目标(mock fetch,验证重试逻辑、超时行为等)。建议后续补充。

结论

代码质量良好,逻辑正确,重构后结构更清晰。没有发现 bug 或安全问题,可以合并。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

push/pull 网络请求无超时和重试机制

2 participants