• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

predis / predis / 20455852140

23 Dec 2025 08:40AM UTC coverage: 92.615% (-0.2%) from 92.788%
20455852140

push

github

web-flow
Added retry support (#1616)

* Initial work on retries

* Added retry class and test coverage

* Added support for standalone and cluster

* Make TimeoutException instance of CommunicationException

* Added pipeline, trasnaction, replication support

* Fixed broken test

* Marked test as relay-incompatible

* Marked test as relay-incompatible

* Fixed analysis errors, added missing tests

* Codestyle fixes

* Fixed test

* Update README.md

* Update README.md

* Update README.md

* Updated README.md

* Refactor retry on read and write

* Added check for timeout value

* Updated README.md

* Fixed README.md

* Codestyle changes

* Added missing coverage

* Added missing test coverage

* Removed comments

* Added retry support for Relay connection (#1620)

* Added integration test case with mocked retry

* Changed client initialisation in tests

* Marked test as relay-incompatible

---------

Co-authored-by: Pavlo Yatsukhnenko <yatsukhnenko@users.noreply.github.com>

301 of 358 new or added lines in 18 files covered. (84.08%)

2 existing lines in 2 files now uncovered.

8214 of 8869 relevant lines covered (92.61%)

112.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.94
/src/Retry/Retry.php
1
<?php
2

3
/*
4
 * This file is part of the Predis package.
5
 *
6
 * (c) 2009-2020 Daniele Alessandri
7
 * (c) 2021-2025 Till Krüss
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12

13
namespace Predis\Retry;
14

15
use Predis\Connection\ConnectionException;
16
use Predis\Connection\Resource\Exception\StreamInitException;
17
use Predis\Retry\Strategy\RetryStrategyInterface;
18
use Predis\TimeoutException;
19
use Throwable;
20

21
class Retry
22
{
23
    /**
24
     * @var RetryStrategyInterface
25
     */
26
    protected $backoffStrategy;
27

28
    /**
29
     * @var int
30
     */
31
    protected $retries;
32

33
    /**
34
     * @var array
35
     */
36
    protected $catchableExceptions = [
37
        TimeoutException::class,
38
        ConnectionException::class,
39
        StreamInitException::class,
40
    ];
41

42
    /**
43
     * @param RetryStrategyInterface $backoffStrategy
44
     * @param int                    $retries
45
     * @param array|null             $catchableExceptions A list of exceptions classes that should be caught.
46
     *                                                    Overrides default list of the catchable exceptions.
47
     */
48
    public function __construct(
2,078✔
49
        RetryStrategyInterface $backoffStrategy,
50
        int $retries,
51
        ?array $catchableExceptions = null
52
    ) {
53
        $this->backoffStrategy = $backoffStrategy;
2,078✔
54
        $this->retries = $retries;
2,078✔
55

56
        if (null !== $catchableExceptions) {
2,078✔
57
            $this->catchableExceptions = $catchableExceptions;
16✔
58
        }
59
    }
60

61
    /**
62
     * Update the retry count.
63
     *
64
     * @param  int  $retries
65
     * @return void
66
     */
67
    public function updateRetriesCount(int $retries): void
4✔
68
    {
69
        $this->retries = $retries;
4✔
70
    }
71

72
    /**
73
     * Extend catchable exceptions list.
74
     *
75
     * @param  array $catchableExceptions
76
     * @return void
77
     */
78
    public function updateCatchableExceptions(array $catchableExceptions): void
55✔
79
    {
80
        $this->catchableExceptions = array_merge($this->catchableExceptions, $catchableExceptions);
55✔
81
    }
82

83
    /**
84
     * @return int
85
     */
86
    public function getRetries(): int
4✔
87
    {
88
        return $this->retries;
4✔
89
    }
90

91
    /**
92
     * @return RetryStrategyInterface
93
     */
NEW
94
    public function getStrategy(): RetryStrategyInterface
×
95
    {
NEW
96
        return $this->backoffStrategy;
×
97
    }
98

99
    /**
100
     * @param  callable(): mixed              $do
101
     * @param  callable(Throwable): void|null $fail
102
     * @return mixed
103
     * @throws Throwable
104
     */
105
    public function callWithRetry(callable $do, ?callable $fail = null)
1,657✔
106
    {
107
        $failures = 0;
1,657✔
108

109
        while (true) {
1,657✔
110
            try {
111
                return $do();
1,657✔
112
            } catch (Throwable $e) {
44✔
113
                if (null !== $this->catchableExceptions) {
44✔
114
                    $isCatchable = false;
44✔
115
                    foreach ($this->catchableExceptions as $catchableException) {
44✔
116
                        if ($e instanceof $catchableException) {
44✔
117
                            $isCatchable = true;
38✔
118
                        }
119
                    }
120

121
                    if (!$isCatchable) {
44✔
122
                        throw $e;
7✔
123
                    }
124
                }
125

126
                $backoff = $this->backoffStrategy->compute($failures);
38✔
127
                ++$failures;
38✔
128

129
                if ($this->retries >= 0 && $failures > $this->retries) {
38✔
130
                    throw $e;
10✔
131
                }
132

133
                if ($fail !== null) {
38✔
134
                    $fail($e);
34✔
135
                }
136

137
                if ($backoff > 0) {
38✔
138
                    usleep($backoff);
30✔
139
                }
140
            }
141
        }
142
    }
143
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc