PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.15.5
Independent Analytics – WordPress Analytics Plugin v2.15.5
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / illuminate / database / Concerns / ManagesTransactions.php
independent-analytics / vendor / illuminate / database / Concerns Last commit date
BuildsQueries.php 1 month ago CompilesJsonPaths.php 1 month ago ExplainsQueries.php 2 years ago ManagesTransactions.php 1 month ago ParsesSearchPath.php 1 month ago
ManagesTransactions.php
280 lines
1 <?php
2
3 namespace IAWPSCOPED\Illuminate\Database\Concerns;
4
5 use Closure;
6 use IAWPSCOPED\Illuminate\Database\DeadlockException;
7 use RuntimeException;
8 use Throwable;
9 /** @internal */
10 trait ManagesTransactions
11 {
12 /**
13 * Execute a Closure within a transaction.
14 *
15 * @param \Closure $callback
16 * @param int $attempts
17 * @return mixed
18 *
19 * @throws \Throwable
20 */
21 public function transaction(Closure $callback, $attempts = 1)
22 {
23 for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
24 $this->beginTransaction();
25 // We'll simply execute the given callback within a try / catch block and if we
26 // catch any exception we can rollback this transaction so that none of this
27 // gets actually persisted to a database or stored in a permanent fashion.
28 try {
29 $callbackResult = $callback($this);
30 } catch (Throwable $e) {
31 $this->handleTransactionException($e, $currentAttempt, $attempts);
32 continue;
33 }
34 try {
35 if ($this->transactions == 1) {
36 $this->fireConnectionEvent('committing');
37 $this->getPdo()->commit();
38 }
39 $this->transactions = \max(0, $this->transactions - 1);
40 if ($this->afterCommitCallbacksShouldBeExecuted()) {
41 $this->transactionsManager?->commit($this->getName());
42 }
43 } catch (Throwable $e) {
44 $this->handleCommitTransactionException($e, $currentAttempt, $attempts);
45 continue;
46 }
47 $this->fireConnectionEvent('committed');
48 return $callbackResult;
49 }
50 }
51 /**
52 * Handle an exception encountered when running a transacted statement.
53 *
54 * @param \Throwable $e
55 * @param int $currentAttempt
56 * @param int $maxAttempts
57 * @return void
58 *
59 * @throws \Throwable
60 */
61 protected function handleTransactionException(Throwable $e, $currentAttempt, $maxAttempts)
62 {
63 // On a deadlock, MySQL rolls back the entire transaction so we can't just
64 // retry the query. We have to throw this exception all the way out and
65 // let the developer handle it in another way. We will decrement too.
66 if ($this->causedByConcurrencyError($e) && $this->transactions > 1) {
67 $this->transactions--;
68 $this->transactionsManager?->rollback($this->getName(), $this->transactions);
69 throw new DeadlockException($e->getMessage(), \is_int($e->getCode()) ? $e->getCode() : 0, $e);
70 }
71 // If there was an exception we will rollback this transaction and then we
72 // can check if we have exceeded the maximum attempt count for this and
73 // if we haven't we will return and try this query again in our loop.
74 $this->rollBack();
75 if ($this->causedByConcurrencyError($e) && $currentAttempt < $maxAttempts) {
76 return;
77 }
78 throw $e;
79 }
80 /**
81 * Start a new database transaction.
82 *
83 * @return void
84 *
85 * @throws \Throwable
86 */
87 public function beginTransaction()
88 {
89 $this->createTransaction();
90 $this->transactions++;
91 $this->transactionsManager?->begin($this->getName(), $this->transactions);
92 $this->fireConnectionEvent('beganTransaction');
93 }
94 /**
95 * Create a transaction within the database.
96 *
97 * @return void
98 *
99 * @throws \Throwable
100 */
101 protected function createTransaction()
102 {
103 if ($this->transactions == 0) {
104 $this->reconnectIfMissingConnection();
105 try {
106 $this->getPdo()->beginTransaction();
107 } catch (Throwable $e) {
108 $this->handleBeginTransactionException($e);
109 }
110 } elseif ($this->transactions >= 1 && $this->queryGrammar->supportsSavepoints()) {
111 $this->createSavepoint();
112 }
113 }
114 /**
115 * Create a save point within the database.
116 *
117 * @return void
118 *
119 * @throws \Throwable
120 */
121 protected function createSavepoint()
122 {
123 $this->getPdo()->exec($this->queryGrammar->compileSavepoint('trans' . ($this->transactions + 1)));
124 }
125 /**
126 * Handle an exception from a transaction beginning.
127 *
128 * @param \Throwable $e
129 * @return void
130 *
131 * @throws \Throwable
132 */
133 protected function handleBeginTransactionException(Throwable $e)
134 {
135 if ($this->causedByLostConnection($e)) {
136 $this->reconnect();
137 $this->getPdo()->beginTransaction();
138 } else {
139 throw $e;
140 }
141 }
142 /**
143 * Commit the active database transaction.
144 *
145 * @return void
146 *
147 * @throws \Throwable
148 */
149 public function commit()
150 {
151 if ($this->transactionLevel() == 1) {
152 $this->fireConnectionEvent('committing');
153 $this->getPdo()->commit();
154 }
155 $this->transactions = \max(0, $this->transactions - 1);
156 if ($this->afterCommitCallbacksShouldBeExecuted()) {
157 $this->transactionsManager?->commit($this->getName());
158 }
159 $this->fireConnectionEvent('committed');
160 }
161 /**
162 * Determine if after commit callbacks should be executed.
163 *
164 * @return bool
165 */
166 protected function afterCommitCallbacksShouldBeExecuted()
167 {
168 return $this->transactions == 0 || $this->transactionsManager && $this->transactionsManager->callbackApplicableTransactions()->count() === 1;
169 }
170 /**
171 * Handle an exception encountered when committing a transaction.
172 *
173 * @param \Throwable $e
174 * @param int $currentAttempt
175 * @param int $maxAttempts
176 * @return void
177 *
178 * @throws \Throwable
179 */
180 protected function handleCommitTransactionException(Throwable $e, $currentAttempt, $maxAttempts)
181 {
182 $this->transactions = \max(0, $this->transactions - 1);
183 if ($this->causedByConcurrencyError($e) && $currentAttempt < $maxAttempts) {
184 return;
185 }
186 if ($this->causedByLostConnection($e)) {
187 $this->transactions = 0;
188 }
189 throw $e;
190 }
191 /**
192 * Rollback the active database transaction.
193 *
194 * @param int|null $toLevel
195 * @return void
196 *
197 * @throws \Throwable
198 */
199 public function rollBack($toLevel = null)
200 {
201 // We allow developers to rollback to a certain transaction level. We will verify
202 // that this given transaction level is valid before attempting to rollback to
203 // that level. If it's not we will just return out and not attempt anything.
204 $toLevel = \is_null($toLevel) ? $this->transactions - 1 : $toLevel;
205 if ($toLevel < 0 || $toLevel >= $this->transactions) {
206 return;
207 }
208 // Next, we will actually perform this rollback within this database and fire the
209 // rollback event. We will also set the current transaction level to the given
210 // level that was passed into this method so it will be right from here out.
211 try {
212 $this->performRollBack($toLevel);
213 } catch (Throwable $e) {
214 $this->handleRollBackException($e);
215 }
216 $this->transactions = $toLevel;
217 $this->transactionsManager?->rollback($this->getName(), $this->transactions);
218 $this->fireConnectionEvent('rollingBack');
219 }
220 /**
221 * Perform a rollback within the database.
222 *
223 * @param int $toLevel
224 * @return void
225 *
226 * @throws \Throwable
227 */
228 protected function performRollBack($toLevel)
229 {
230 if ($toLevel == 0) {
231 $pdo = $this->getPdo();
232 if ($pdo->inTransaction()) {
233 $pdo->rollBack();
234 }
235 } elseif ($this->queryGrammar->supportsSavepoints()) {
236 $this->getPdo()->exec($this->queryGrammar->compileSavepointRollBack('trans' . ($toLevel + 1)));
237 }
238 }
239 /**
240 * Handle an exception from a rollback.
241 *
242 * @param \Throwable $e
243 * @return void
244 *
245 * @throws \Throwable
246 */
247 protected function handleRollBackException(Throwable $e)
248 {
249 if ($this->causedByLostConnection($e)) {
250 $this->transactions = 0;
251 $this->transactionsManager?->rollback($this->getName(), $this->transactions);
252 }
253 throw $e;
254 }
255 /**
256 * Get the number of active transactions.
257 *
258 * @return int
259 */
260 public function transactionLevel()
261 {
262 return $this->transactions;
263 }
264 /**
265 * Execute the callback after a transaction commits.
266 *
267 * @param callable $callback
268 * @return void
269 *
270 * @throws \RuntimeException
271 */
272 public function afterCommit($callback)
273 {
274 if ($this->transactionsManager) {
275 return $this->transactionsManager->addCallback($callback);
276 }
277 throw new RuntimeException('Transactions Manager has not been set.');
278 }
279 }
280