Skip to content

Conversation

@huangdijia
Copy link
Contributor

@huangdijia huangdijia commented Dec 5, 2025

Summary

  • 新增BackoffInterface接口定义统一规范
  • 实现6种不同的Backoff重试策略以适应不同场景需求
  • 所有策略统一使用毫秒作为时间单位
  • 支持配置延迟上限以防止过度等待
  • 提供完整的单元测试覆盖,确保代码质量

Features

  • FixedBackoff: 固定延迟策略,适用于需要恒定重试间隔的场景
  • LinearBackoff: 线性增长延迟,延迟值按固定步长递增
  • ExponentialBackoff: 指数增长延迟,支持抖动防止雷群效应
  • FibonacciBackoff: 基于斐波那契数列的延迟策略
  • DecorrelatedJitterBackoff: AWS最佳实践的去相关抖动策略
  • PoissonBackoff: 基于泊松分布的随机延迟策略

Test Coverage

  • BackoffTestCase: 抽象测试基类,提供通用测试方法
  • FixedBackoffTest: 100%覆盖FixedBackoff功能
  • LinearBackoffTest: 100%覆盖LinearBackoff功能
  • ExponentialBackoffTest: 100%覆盖ExponentialBackoff功能
  • FibonacciBackoffTest: 100%覆盖FibonacciBackoff功能
  • DecorrelatedJitterBackoffTest: 100%覆盖DecorrelatedJitterBackoff功能
  • PoissonBackoffTest: 100%覆盖PoissonBackoff功能

测试包括:

  • 接口实现验证
  • 默认参数测试
  • 自定义参数测试
  • 延迟计算正确性
  • 延迟上限限制
  • 重置功能测试
  • 边界条件处理
  • 私有属性访问验证
  • 统计特性验证(Poisson分布)
  • 随机性验证(抖动策略)

Test plan

  • 验证所有Backoff策略实现符合接口定义
  • 测试各策略的延迟计算是否正确
  • 验证延迟上限限制是否生效
  • 测试reset()方法功能
  • 测试getAttempt()计数器功能
  • 验证默认参数值是否合理
  • 检查代码质量和注释完整性
  • 运行所有单元测试确保通过

Summary by CodeRabbit

发布说明

  • 新功能

    • 新增退避接口与抽象基类,统一重试计数、睡眠行为并返回实际延迟。
    • 增加多种退避策略:固定、线性、指数(可选抖动)、斐波那契、相关性抖动和泊松分布,均支持可配置参数与边界处理。
  • 测试

    • 为所有退避策略新增全面单元测试,覆盖默认行为、边界条件、重置与随机性验证。

✏️ Tip: You can customize this high-level summary in your review settings.

- 新增BackoffInterface接口定义
- 实现FixedBackoff: 固定延迟策略
- 实现LinearBackoff: 线性增长延迟策略
- 实现ExponentialBackoff: 指数增长延迟策略(支持抖动)
- 实现FibonacciBackoff: 斐波那契序列延迟策略
- 实现DecorrelatedJitterBackoff: 去相关抖动延迟策略
- 实现PoissonBackoff: 泊松分布随机延迟策略

所有策略统一使用毫秒作为时间单位,支持延迟上限设置,
适用于不同场景的重试需求。
Copilot AI review requested due to automatic review settings December 5, 2025 09:53
@coderabbitai

This comment was marked as spam.

- 新增BackoffTestCase抽象基类,包含通用测试方法
- 新增FixedBackoffTest:测试固定延迟策略
- 新增LinearBackoffTest:测试线性增长延迟策略
- 新增ExponentialBackoffTest:测试指数增长延迟策略
- 新增FibonacciBackoffTest:测试斐波那契序列延迟策略
- 新增DecorrelatedJitterBackoffTest:测试去相关抖动延迟策略
- 新增PoissonBackoffTest:测试泊松分布随机延迟策略

所有测试类覆盖:
- 接口实现验证
- 参数配置测试
- 延迟计算正确性
- 延迟上限限制
- 重置功能
- 边界条件测试
- 私有属性访问验证
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (5)
src/support/src/Backoff/FibonacciBackoff.php (1)

41-44: 建议:考虑添加初始延迟参数以提高灵活性。

当前实现中,斐波那契数列从 1ms 开始(序列为 1, 1, 2, 3, 5, 8...),这与其他策略(如 FixedBackoff 默认 500ms,ExponentialBackoff 默认 100ms)相比显得较小。建议考虑添加一个乘数或基础延迟参数,以便用户能够调整初始延迟范围。

-    public function __construct(int $max = 10000)
+    public function __construct(int $base = 100, int $max = 10000)
     {
+        $this->base = $base;
         $this->max = $max;
     }

然后在 next() 中使用 $delay = $this->curr * $this->base;

src/support/src/Backoff/PoissonBackoff.php (1)

16-16: 建议:将中文注释改为英文以保持代码一致性。

其他 Backoff 类使用英文注释,建议保持一致。

-    private int $mean;     // 平均延迟
+    private int $mean;     // Mean delay (milliseconds)
src/support/src/Backoff/FixedBackoff.php (1)

14-20: 建议:类描述过于具体。

类注释提到 "email retry mechanism",但这是一个通用的 Backoff 策略实现。建议将描述改为更通用的表述。

 /**
- * Fixed backoff implementation for email retry mechanism.
+ * Fixed backoff implementation.
  *
  * This class provides a simple backoff strategy where the delay between
  * retry attempts remains constant (fixed). It's useful when you want
  * predictable retry intervals regardless of how many attempts have been made.
  */
src/support/src/Backoff/DecorrelatedJitterBackoff.php (2)

14-14: 建议添加类级别的文档块。

LinearBackoff 相比,此类缺少描述去相关抖动算法的类级别文档块。建议添加以保持一致性并解释 AWS 最佳实践的实现细节。

+/**
+ * Decorrelated jitter backoff strategy implementation.
+ *
+ * This class implements the decorrelated jitter algorithm based on AWS best practices.
+ * The delay is randomized between the base value and the previous delay multiplied
+ * by a factor, which helps spread out retry attempts across distributed systems.
+ *
+ * @see https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
+ */
 class DecorrelatedJitterBackoff implements BackoffInterface

90-96: 文档注释与实际行为不一致。

注释标注为 "1-based attempt index",但 $attempt 初始值为 0,行为与 LinearBackoff(标注为 "0-based")完全相同。建议统一文档描述以避免混淆。

     /**
-     * 1-based attempt index.
+     * Get the current attempt number.
+     *
+     * @return int The current attempt number (0-based, incremented after each next() call)
      */
     public function getAttempt(): int
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1d45f8 and 78850e9.

📒 Files selected for processing (7)
  • src/support/src/Backoff/BackoffInterface.php (1 hunks)
  • src/support/src/Backoff/DecorrelatedJitterBackoff.php (1 hunks)
  • src/support/src/Backoff/ExponentialBackoff.php (1 hunks)
  • src/support/src/Backoff/FibonacciBackoff.php (1 hunks)
  • src/support/src/Backoff/FixedBackoff.php (1 hunks)
  • src/support/src/Backoff/LinearBackoff.php (1 hunks)
  • src/support/src/Backoff/PoissonBackoff.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/*/src/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All components use the namespace pattern: FriendsOfHyperf\{ComponentName}

Files:

  • src/support/src/Backoff/BackoffInterface.php
  • src/support/src/Backoff/LinearBackoff.php
  • src/support/src/Backoff/DecorrelatedJitterBackoff.php
  • src/support/src/Backoff/PoissonBackoff.php
  • src/support/src/Backoff/ExponentialBackoff.php
  • src/support/src/Backoff/FibonacciBackoff.php
  • src/support/src/Backoff/FixedBackoff.php
**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.php: Follow PSR-12 coding standards for all PHP code
Use PHP-CS-Fixer for code formatting as configured in .php-cs-fixer.php
Use PHPStan for static analysis as configured in phpstan.neon.dist

Files:

  • src/support/src/Backoff/BackoffInterface.php
  • src/support/src/Backoff/LinearBackoff.php
  • src/support/src/Backoff/DecorrelatedJitterBackoff.php
  • src/support/src/Backoff/PoissonBackoff.php
  • src/support/src/Backoff/ExponentialBackoff.php
  • src/support/src/Backoff/FibonacciBackoff.php
  • src/support/src/Backoff/FixedBackoff.php
🧬 Code graph analysis (7)
src/support/src/Backoff/BackoffInterface.php (6)
src/support/src/Backoff/DecorrelatedJitterBackoff.php (3)
  • next (62-79)
  • reset (84-88)
  • getAttempt (93-96)
src/support/src/Backoff/ExponentialBackoff.php (3)
  • next (73-94)
  • reset (99-102)
  • getAttempt (107-110)
src/support/src/Backoff/FibonacciBackoff.php (3)
  • next (49-63)
  • reset (68-73)
  • getAttempt (78-81)
src/support/src/Backoff/FixedBackoff.php (3)
  • next (54-58)
  • reset (68-71)
  • getAttempt (82-85)
src/support/src/Backoff/LinearBackoff.php (3)
  • next (71-85)
  • reset (93-96)
  • getAttempt (106-109)
src/support/src/Backoff/PoissonBackoff.php (3)
  • next (28-48)
  • reset (50-53)
  • getAttempt (55-58)
src/support/src/Backoff/LinearBackoff.php (2)
src/support/src/Backoff/FixedBackoff.php (3)
  • next (54-58)
  • reset (68-71)
  • getAttempt (82-85)
src/support/src/Backoff/BackoffInterface.php (3)
  • next (16-16)
  • reset (18-18)
  • getAttempt (20-20)
src/support/src/Backoff/DecorrelatedJitterBackoff.php (2)
src/support/src/Backoff/FixedBackoff.php (4)
  • __construct (40-43)
  • next (54-58)
  • reset (68-71)
  • getAttempt (82-85)
src/support/src/Backoff/BackoffInterface.php (3)
  • next (16-16)
  • reset (18-18)
  • getAttempt (20-20)
src/support/src/Backoff/PoissonBackoff.php (1)
src/support/src/Backoff/BackoffInterface.php (3)
  • next (16-16)
  • reset (18-18)
  • getAttempt (20-20)
src/support/src/Backoff/ExponentialBackoff.php (1)
src/support/src/Backoff/BackoffInterface.php (3)
  • next (16-16)
  • reset (18-18)
  • getAttempt (20-20)
src/support/src/Backoff/FibonacciBackoff.php (3)
src/support/src/Backoff/FixedBackoff.php (4)
  • __construct (40-43)
  • next (54-58)
  • reset (68-71)
  • getAttempt (82-85)
src/support/src/Backoff/LinearBackoff.php (4)
  • __construct (52-57)
  • next (71-85)
  • reset (93-96)
  • getAttempt (106-109)
src/support/src/Backoff/BackoffInterface.php (3)
  • next (16-16)
  • reset (18-18)
  • getAttempt (20-20)
src/support/src/Backoff/FixedBackoff.php (1)
src/support/src/Backoff/BackoffInterface.php (3)
  • next (16-16)
  • reset (18-18)
  • getAttempt (20-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: Test on PHP 8.2 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.1 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.2 with Swoole 6.1.3
  • GitHub Check: Test on PHP 8.2 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.1 with Swoole 6.1.3
  • GitHub Check: Test on PHP 8.1 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.3 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.3 with Swoole 6.1.3
  • GitHub Check: Test on PHP 8.3 with Swoole 6.0.2
  • GitHub Check: Seer Code Review
  • GitHub Check: Test on PHP 8.1 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.2 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.3 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.1 with Swoole 6.1.3
  • GitHub Check: Test on PHP 8.3 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.3 with Swoole 6.1.3
  • GitHub Check: Test on PHP 8.2 with Swoole 6.1.3
  • GitHub Check: Test on PHP 8.2 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.1 with Swoole 6.0.2
  • GitHub Check: Agent
🔇 Additional comments (9)
src/support/src/Backoff/BackoffInterface.php (1)

14-21: 接口设计简洁清晰!

接口定义了三个核心方法,符合单一职责原则。所有具体的 Backoff 策略实现都遵循此接口规范,便于多态使用和策略切换。

src/support/src/Backoff/FibonacciBackoff.php (1)

49-63: 斐波那契逻辑实现正确!

使用数组解构进行状态更新的写法简洁且正确,避免了临时变量的使用。延迟上限限制也正确实现。

src/support/src/Backoff/FixedBackoff.php (1)

40-58: 实现简洁正确!

固定延迟策略的实现清晰明了,文档注释完整,符合接口规范。

src/support/src/Backoff/ExponentialBackoff.php (1)

73-94: 指数退避与抖动实现正确!

使用 random_int() 实现抖动是安全的做法(密码学安全的随机数生成器),有效防止了重试风暴(thundering herd)问题。先应用上限再添加抖动的顺序也是正确的。

src/support/src/Backoff/LinearBackoff.php (4)

1-23: LGTM!

命名空间遵循 FriendsOfHyperf\{ComponentName} 模式,类文档块清晰地描述了线性退避算法的公式和行为。


25-57: LGTM!

属性定义清晰,构造函数默认参数合理。


71-85: LGTM!

线性延迟计算逻辑正确,先使用当前 attempt 计算延迟,再递增计数器,确保首次调用返回 initial 值。


93-109: LGTM!

reset()getAttempt() 方法实现符合 BackoffInterface 接口规范,与 FixedBackoff 保持一致。

src/support/src/Backoff/DecorrelatedJitterBackoff.php (1)

84-88: LGTM!

reset() 方法正确重置了 attemptprevDelay 两个状态属性,确保退避策略可以从头开始。

- 修复DecorrelatedJitterBackoffTest中的预期值问题
- 为非确定性策略(使用随机数的策略)添加isDeterministic()方法
- 修正测试用例以正确处理随机延迟范围
- 所有94个测试用例现在都能正常通过

This comment was marked as spam.

huangdijia and others added 4 commits December 5, 2025 18:01
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
- 添加max()函数确保upper bound不小于base,避免random_int()参数错误
- 修复类声明缺少开大括号的语法错误
- 增加factor < 1.0和factor = 0的边界测试用例
- 所有97个Backoff测试用例现在都能正常通过
coderabbitai[bot]

This comment was marked as spam.

- 修复Knuth算法在mean > 700时exp(-mean)下溢为0的问题
- 根据均值大小使用不同算法:
  * mean <= 30: 使用原始Knuth算法
  * 30 < mean <= 700: 使用正态分布近似
  * mean > 700: 使用Box-Muller变换的截断正态分布
- 确保延迟值不为负数
- 更新默认均值为100,更适合典型延迟场景
- 添加大均值测试用例验证修复效果
- 所有99个测试用例全部通过
Copy link
Contributor Author

@huangdijia huangdijia left a comment

Choose a reason for hiding this comment

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

代码审查报告

变更总结

本 PR 为 friendsofhyperf/components 添加了完整的 Backoff(退避)重试策略实现,包括:

  • BackoffInterface 统一接口
  • 6种退避策略实现
  • 完整的单元测试覆盖

潜在风险

高风险

  1. PoissonBackoff 数值稳定性
    • 虽已修复数值下溢问题,但极端边界情况下仍需关注

中风险

  1. 静态变量状态污染

    • PoissonBackoff 使用静态变量可能影响长时间运行的应用
  2. 性能考虑

    • gaussRandom() 方法的三角函数计算开销

优化建议

  1. 使用实例变量替代静态变量
  2. 添加参数验证和异常处理
  3. 统一边界值处理策略

合规性

  • ✅ 符合 PSR-12 编码规范
  • ✅ 命名约定符合项目标准
  • ✅ 测试覆盖率优秀(99个测试用例)
  • ⚠️ 建议:统一使用英文注释

总体评价

高质量的代码实现,设计合理,测试完整。建议在合并前处理注释一致性问题。

Copy link
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

Copilot reviewed 14 out of 14 changed files in this pull request and generated 11 comments.

Copy link
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

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

huangdijia and others added 2 commits December 5, 2025 21:54
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@huangdijia huangdijia merged commit 41908f3 into main Dec 5, 2025
21 of 22 checks passed
@huangdijia huangdijia deleted the feat/add-backoff-strategies branch December 5, 2025 14:01
huangdijia added a commit that referenced this pull request Dec 5, 2025
* feat: 添加多种Backoff重试策略实现

- 新增BackoffInterface接口定义
- 实现FixedBackoff: 固定延迟策略
- 实现LinearBackoff: 线性增长延迟策略
- 实现ExponentialBackoff: 指数增长延迟策略(支持抖动)
- 实现FibonacciBackoff: 斐波那契序列延迟策略
- 实现DecorrelatedJitterBackoff: 去相关抖动延迟策略
- 实现PoissonBackoff: 泊松分布随机延迟策略

所有策略统一使用毫秒作为时间单位,支持延迟上限设置,
适用于不同场景的重试需求。

* test: 添加Backoff策略的单元测试

- 新增BackoffTestCase抽象基类,包含通用测试方法
- 新增FixedBackoffTest:测试固定延迟策略
- 新增LinearBackoffTest:测试线性增长延迟策略
- 新增ExponentialBackoffTest:测试指数增长延迟策略
- 新增FibonacciBackoffTest:测试斐波那契序列延迟策略
- 新增DecorrelatedJitterBackoffTest:测试去相关抖动延迟策略
- 新增PoissonBackoffTest:测试泊松分布随机延迟策略

所有测试类覆盖:
- 接口实现验证
- 参数配置测试
- 延迟计算正确性
- 延迟上限限制
- 重置功能
- 边界条件测试
- 私有属性访问验证

* fix: 修复Backoff策略单元测试中的随机性问题

- 修复DecorrelatedJitterBackoffTest中的预期值问题
- 为非确定性策略(使用随机数的策略)添加isDeterministic()方法
- 修正测试用例以正确处理随机延迟范围
- 所有94个测试用例现在都能正常通过

* feat: 更新BackoffInterface接口文档,增加方法注释以提高可读性

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* feat: 更新PoissonBackoff和测试用例,优化文档注释和代码格式

* fix: 修复DecorrelatedJitterBackoff中factor < 1.0时random_int()异常问题

- 添加max()函数确保upper bound不小于base,避免random_int()参数错误
- 修复类声明缺少开大括号的语法错误
- 增加factor < 1.0和factor = 0的边界测试用例
- 所有97个Backoff测试用例现在都能正常通过

* fix: 修复PoissonBackoff中大均值导致的数值下溢和无限循环问题

- 修复Knuth算法在mean > 700时exp(-mean)下溢为0的问题
- 根据均值大小使用不同算法:
  * mean <= 30: 使用原始Knuth算法
  * 30 < mean <= 700: 使用正态分布近似
  * mean > 700: 使用Box-Muller变换的截断正态分布
- 确保延迟值不为负数
- 更新默认均值为100,更适合典型延迟场景
- 添加大均值测试用例验证修复效果
- 所有99个测试用例全部通过

* fix: 优化PoissonBackoff中的延迟返回逻辑,确保返回值不为负数

* feat: 更新PoissonBackoff类中的注释,确保代码可读性和一致性

* feat: 重构后退策略类,统一继承自AbstractBackoff,优化参数验证和延迟计算逻辑

* feat: 优化AbstractBackoff和LinearBackoff类,移除未使用的变量,提升代码整洁性

* feat: 更新PoissonBackoff类中的参数注释,增强代码可读性

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* feat: 更新后退策略构造函数参数类型为正整数,增强参数验证

* feat: 添加sleep方法到后退策略接口,提供延迟等待功能并返回延迟时间

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: 移除多余的空行,优化代码可读性

---------

Co-authored-by: Deeka Wong <8337659+huangdijia@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
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