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: /**
29: * The strategy to follow should the executed action fail.
30: *
31: * @var \Cake\Core\Retry\RetryStrategyInterface
32: */
33: protected $strategy;
34:
35: /**
36: * The number of retries to perform in case of failure.
37: *
38: * @var int
39: */
40: protected $retries;
41:
42: /**
43: * Creates the CommandRetry object with the given strategy and retry count
44: *
45: * @param \Cake\Core\Retry\RetryStrategyInterface $strategy The strategy to follow should the action fail
46: * @param int $retries The number of times the action has been already called
47: */
48: public function __construct(RetryStrategyInterface $strategy, $retries = 1)
49: {
50: $this->strategy = $strategy;
51: $this->retries = $retries;
52: }
53:
54: /**
55: * The number of retries to perform in case of failure
56: *
57: * @param callable $action The callable action to execute with a retry strategy
58: * @return mixed The return value of the passed action callable
59: * @throws \Exception
60: */
61: public function run(callable $action)
62: {
63: $retryCount = 0;
64: $lastException = null;
65:
66: do {
67: try {
68: return $action();
69: } catch (Exception $e) {
70: $lastException = $e;
71: if (!$this->strategy->shouldRetry($e, $retryCount)) {
72: throw $e;
73: }
74: }
75: } while ($this->retries > $retryCount++);
76:
77: if ($lastException !== null) {
78: throw $lastException;
79: }
80: }
81: }
82: