Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
66.67% covered (warning)
66.67%
2 / 3
CRAP
83.33% covered (warning)
83.33%
15 / 18
MultiplierRetryStrategy
0.00% covered (danger)
0.00%
0 / 1
66.67% covered (warning)
66.67%
2 / 3
8.30
83.33% covered (warning)
83.33%
15 / 18
 __construct
0.00% covered (danger)
0.00%
0 / 1
4.32
72.73% covered (warning)
72.73%
8 / 11
 isRetryable
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getWaitingTime
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
5 / 5
<?php
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Component\Messenger\Retry;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
use Symfony\Component\Messenger\Stamp\RedeliveryStamp;
/**
 * A retry strategy with a constant or exponential retry delay.
 *
 * For example, if $delayMilliseconds=10000 & $multiplier=1 (default),
 * each retry will wait exactly 10 seconds.
 *
 * But if $delayMilliseconds=10000 & $multiplier=2:
 *      * Retry 1: 10 second delay
 *      * Retry 2: 20 second delay (10000 * 2 = 20000)
 *      * Retry 3: 40 second delay (20000 * 2 = 40000)
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 *
 * @final
 */
class MultiplierRetryStrategy implements RetryStrategyInterface
{
    private $maxRetries;
    private $delayMilliseconds;
    private $multiplier;
    private $maxDelayMilliseconds;
    /**
     * @param int   $maxRetries           The maximum number of times to retry
     * @param int   $delayMilliseconds    Amount of time to delay (or the initial value when multiplier is used)
     * @param float $multiplier           Multiplier to apply to the delay each time a retry occurs
     * @param int   $maxDelayMilliseconds Maximum delay to allow (0 means no maximum)
     */
    public function __construct(int $maxRetries = 3, int $delayMilliseconds = 1000, float $multiplier = 1, int $maxDelayMilliseconds = 0)
    {
        $this->maxRetries = $maxRetries;
        if ($delayMilliseconds < 0) {
            throw new InvalidArgumentException(sprintf('Delay must be greater than or equal to zero: "%s" passed.', $delayMilliseconds));
        }
        $this->delayMilliseconds = $delayMilliseconds;
        if ($multiplier < 1) {
            throw new InvalidArgumentException(sprintf('Multiplier must be greater than zero: "%s" passed.', $multiplier));
        }
        $this->multiplier = $multiplier;
        if ($maxDelayMilliseconds < 0) {
            throw new InvalidArgumentException(sprintf('Max delay must be greater than or equal to zero: "%s" passed.', $maxDelayMilliseconds));
        }
        $this->maxDelayMilliseconds = $maxDelayMilliseconds;
    }
    public function isRetryable(Envelope $message): bool
    {
        $retries = RedeliveryStamp::getRetryCountFromEnvelope($message);
        return $retries < $this->maxRetries;
    }
    public function getWaitingTime(Envelope $message): int
    {
        $retries = RedeliveryStamp::getRetryCountFromEnvelope($message);
        $delay = $this->delayMilliseconds * pow($this->multiplier, $retries);
        if ($delay > $this->maxDelayMilliseconds && 0 !== $this->maxDelayMilliseconds) {
            return $this->maxDelayMilliseconds;
        }
        return $delay;
    }
}