GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#160)
by joseph
22:55
created

RetryConnection::prepareWrapped()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\EntityManager\RetryConnection;
4
5
use Doctrine\Common\EventManager;
6
use Doctrine\DBAL\Cache\QueryCacheProfile;
7
use Doctrine\DBAL\Configuration;
8
use Doctrine\DBAL\Connection;
9
use Doctrine\DBAL\Driver;
10
11
/**
12
 * This is a connection wrapper that enables some retry functionality should the connection to the DB be lost for any
13
 * reason. Especially useful on long running processes
14
 */
15
class RetryConnection extends Connection
16
{
17
    private $shouldConnectionByRetried;
18
19
    /** @var \ReflectionProperty */
20
    private $selfReflectionNestingLevelProperty;
21
22
    /**
23
     * RetryConnection constructor.
24
     *
25
     * @param array              $params
26
     * @param Driver             $driver
27
     * @param Configuration|null $config
28
     * @param EventManager|null  $eventManager
29
     *
30
     * @throws \Doctrine\DBAL\DBALException
31
     * @SuppressWarnings(PHPMD.StaticAccess)
32
     */
33
    public function __construct(
34
        array $params,
35
        Driver $driver,
36
        ?Configuration $config = null,
37
        ?EventManager $eventManager = null
38
    ) {
39
        $this->shouldConnectionByRetried = ShouldConnectionByRetried::createWithConfigParams($params);
40
        parent::__construct($params, $driver, $config, $eventManager);
41
    }
42
43
    public function executeUpdate($query, array $params = [], array $types = [])
44
    {
45
        $args = [$query, $params, $types];
46
47
        return $this->connectionWrapper(__FUNCTION__, $args, false);
48
    }
49
50
    private function connectionWrapper(string $function, array $args, bool $ignoreTransaction)
51
    {
52
        $retryConnectionFlag  = true;
53
        $checkRetryConnection = $this->shouldConnectionByRetried;
54
        $numberOfAttempts     = 0;
55
        $result               = null;
56
        while ($retryConnectionFlag === true) {
57
            try {
58
                $retryConnectionFlag = false;
59
                $numberOfAttempts++;
60
                $result = parent::$function(...$args);
61
            } catch (\Exception $exception) {
62
                $nestingLevel        = $this->getTransactionNestingLevel();
63
                $retryConnectionFlag = $checkRetryConnection
64
                    ->checkAndSleep(
65
                        $exception,
66
                        $numberOfAttempts,
67
                        $nestingLevel,
68
                        $ignoreTransaction
69
                    );
70
                if ($retryConnectionFlag === false) {
71
                    throw $exception;
72
                }
73
                $this->close();
74
                $numberOfAttempts++;
75
                if ($ignoreTransaction === true && 0 < $this->getTransactionNestingLevel()) {
76
                    $this->resetTransactionNestingLevel();
77
                }
78
            }
79
        }
80
81
        return $result;
82
    }
83
84
    /**
85
     * This is required because beginTransaction increment _transactionNestingLevel
86
     * before the real query is executed, and results incremented also on gone away error.
87
     * This should be safe for a new established connection.
88
     */
89
    private function resetTransactionNestingLevel(): void
90
    {
91
        if (!$this->selfReflectionNestingLevelProperty instanceof \ReflectionProperty) {
0 ignored issues
show
introduced by
$this->selfReflectionNestingLevelProperty is always a sub-type of ReflectionProperty.
Loading history...
92
            $reflection                               = new \ReflectionClass(Connection::class);
93
            $this->selfReflectionNestingLevelProperty = $reflection->getProperty('_transactionNestingLevel');
94
            $this->selfReflectionNestingLevelProperty->setAccessible(true);
95
        }
96
97
        $this->selfReflectionNestingLevelProperty->setValue($this, 0);
98
    }
99
100
    public function query(...$args)
101
    {
102
        return $this->connectionWrapper('query', $args, false);
103
    }
104
105
    public function executeQuery($query, array $params = [], $types = [], QueryCacheProfile $qcp = null)
106
    {
107
        $args = [$query, $params, $types, $qcp];
108
109
        return $this->connectionWrapper(__FUNCTION__, $args, false);
110
    }
111
112
    public function beginTransaction()
113
    {
114
        if (0 !== $this->getTransactionNestingLevel()) {
115
            parent::beginTransaction();
116
        }
117
        $this->connectionWrapper(__FUNCTION__, [], true);
118
    }
119
120
    public function connect()
121
    {
122
        return $this->connectionWrapper(__FUNCTION__, [], false);
123
    }
124
125
    /**
126
     * @param string $sql
127
     *
128
     * @return Statement
129
     */
130
    public function prepare($sql): Statement
131
    {
132
        return $this->prepareWrapped($sql);
133
    }
134
135
    /**
136
     * returns a reconnect-wrapper for Statements.
137
     *
138
     * @param string $sql
139
     *
140
     * @return Statement
141
     */
142
    protected function prepareWrapped(string $sql): Statement
143
    {
144
        return new Statement($sql, $this, $this->shouldConnectionByRetried);
145
    }
146
147
    /**
148
     * do not use, only used by Statement-class
149
     * needs to be public for access from the Statement-class.
150
     *
151
     * @internal
152
     *
153
     * @param string $sql
154
     *
155
     * @return Driver\Statement
156
     * @throws \Doctrine\DBAL\DBALException
157
     */
158
    public function prepareUnwrapped(string $sql): Driver\Statement
159
    {
160
        // returns the actual statement
161
        return parent::prepare($sql);
162
    }
163
}
164