Passed
Pull Request — 0.9.x (#325)
by Shinji
01:52
created

AutoContextRecovering::onRecover()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of the reliforp/reli-prof package.
5
 *
6
 * (c) sji <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Reli\Inspector\Daemon;
15
16
use Amp\Parallel\Context\ContextException;
0 ignored issues
show
Bug introduced by
The type Amp\Parallel\Context\ContextException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Reli\Lib\Amphp\ContextInterface;
18
use Reli\Lib\Amphp\MessageProtocolInterface;
19
use Reli\Lib\Log\Log;
20
21
/**
22
 * @template T of MessageProtocolInterface
23
 * @implements AutoContextRecoveringInterface<T>
24
 */
25
final class AutoContextRecovering implements AutoContextRecoveringInterface
26
{
27
    private const RETRY_COUNT = 10;
28
29
    /** @var ContextInterface<T>|null */
30
    private ?ContextInterface $context = null;
31
32
    private ?\Closure $on_recover_callback = null;
33
34
    /**
35
     * @param \Closure():ContextInterface<T> $context_factory
36
     */
37
    public function __construct(
38
        private readonly \Closure $context_factory,
39
    ) {
40
    }
41
42
    public function recreateContext(): void
43
    {
44
        if (!is_null($this->context) and $this->context->isRunning()) {
45
            $this->context->stop();
46
        }
47
        $this->context = null;
48
    }
49
50
    public function getContext(): ContextInterface
51
    {
52
        if (is_null($this->context)) {
53
            $this->context = $this->context_factory->__invoke();
54
            if (!is_null($this->on_recover_callback)) {
55
                $this->on_recover_callback->__invoke();
56
            }
57
        }
58
        return $this->context;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->context could return the type null which is incompatible with the type-hinted return Reli\Lib\Amphp\ContextInterface. Consider adding an additional type-check to rule them out.
Loading history...
59
    }
60
61
    public function withAutoRecover(
62
        \Closure $callback,
63
        string $log_message_on_retry,
64
    ): mixed {
65
        for ($i = 0; $i < self::RETRY_COUNT; $i++) {
66
            try {
67
                return $callback($this->getContext()->getProtocol());
68
            } catch (ContextException $e) {
69
                Log::info(
70
                    $log_message_on_retry,
71
                    [
72
                        'exception' => $e,
73
                    ]
74
                );
75
                $this->recreateContext();
76
            }
77
        }
78
        assert($e instanceof \Throwable);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $e does not seem to be defined for all execution paths leading up to this point.
Loading history...
79
        throw $e;
80
    }
81
82
    public function onRecover(\Closure $callback): void
83
    {
84
        $this->on_recover_callback = $callback;
85
    }
86
}
87