1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 3.6.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\Core\Retry;
16:
17: use Exception;
18:
19: /**
20: * Allows any action to be retried in case of an exception.
21: *
22: * This class can be parametrized with a strategy, which will be followed
23: * to determine whether or not the action should be retried.
24: */
25: class CommandRetry
26: {
27: /**
28: * The strategy to follow should the executed action fail.
29: *
30: * @var \Cake\Core\Retry\RetryStrategyInterface
31: */
32: protected $strategy;
33:
34: /**
35: * The number of retries to perform in case of failure.
36: *
37: * @var int
38: */
39: protected $retries;
40:
41: /**
42: * Creates the CommandRetry object with the given strategy and retry count
43: *
44: * @param \Cake\Core\Retry\RetryStrategyInterface $strategy The strategy to follow should the action fail
45: * @param int $retries The number of times the action has been already called
46: */
47: public function __construct(RetryStrategyInterface $strategy, $retries = 1)
48: {
49: $this->strategy = $strategy;
50: $this->retries = $retries;
51: }
52:
53: /**
54: * The number of retries to perform in case of failure
55: *
56: * @param callable $action The callable action to execute with a retry strategy
57: * @return mixed The return value of the passed action callable
58: * @throws \Exception
59: */
60: public function run(callable $action)
61: {
62: $retryCount = 0;
63: $lastException = null;
64:
65: do {
66: try {
67: return $action();
68: } catch (Exception $e) {
69: $lastException = $e;
70: if (!$this->strategy->shouldRetry($e, $retryCount)) {
71: throw $e;
72: }
73: }
74: } while ($this->retries > $retryCount++);
75:
76: if ($lastException !== null) {
77: throw $lastException;
78: }
79: }
80: }
81: