123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- <?php
- declare(strict_types=1);
- /**
- * This file is part of Hyperf.
- *
- * @link https://www.hyperf.io
- * @document https://hyperf.wiki
- * @contact group@hyperf.io
- * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
- */
- namespace Hyperf\Utils;
- class Backoff
- {
- /**
- * Max backoff.
- */
- private const CAP = 60 * 1000; // 1 minute
- /**
- * @var int
- */
- private $firstMs;
- /**
- * Backoff interval.
- * @var int
- */
- private $currentMs;
- /**
- * @param int the first backoff in milliseconds
- */
- public function __construct(int $firstMs = 0)
- {
- if ($firstMs < 0) {
- throw new \InvalidArgumentException(
- 'first backoff interval must be greater or equal than 0'
- );
- }
- if ($firstMs > Backoff::CAP) {
- throw new \InvalidArgumentException(
- sprintf(
- 'first backoff interval must be less or equal than %d milliseconds',
- self::CAP
- )
- );
- }
- $this->firstMs = $firstMs;
- $this->currentMs = $firstMs;
- }
- /**
- * Sleep until the next execution.
- */
- public function sleep(): void
- {
- if ($this->currentMs === 0) {
- return;
- }
- usleep($this->currentMs * 1000);
- // update backoff using Decorrelated Jitter
- // see: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
- $this->currentMs = rand($this->firstMs, $this->currentMs * 3);
- if ($this->currentMs > self::CAP) {
- $this->currentMs = self::CAP;
- }
- }
- /**
- * Get the next backoff for logging, etc.
- * @return int next backoff
- */
- public function nextBackoff(): int
- {
- return $this->currentMs;
- }
- }
|