PluginProbe
404 Solution / 4.3.3
404 Solution v4.3.3
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / database / DatabaseConnectivityErrorTaxonomy.php

DatabaseConnectivityErrorTaxonomy.php in 404 Solution 4.3.3, at includes/database/DatabaseConnectivityErrorTaxonomy.php

133 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Pure database connectivity error taxonomy.
4 *
5 * Owns string-based classification of transport-level failures: network
6 * connection drops, query-execution timeouts, packet size limits, and
7 * deadlock / lock-wait contention. These are the error classes the retry
8 * and staged-build "resumable kill" policies act on.
9 *
10 * No side effects: callers reuse the matchers without inheriting recovery
11 * behavior.
12 */
13
14 if (!defined('ABSPATH')) {
15 exit;
16 }
17
18 // allow-no-test-found: covered through DatabaseInfrastructureErrorTaxonomy facade by tests/ErrorClassifierTest.php and tests/StagedBuildHostQuirksTest.php
19 class ABJ_404_Solution_DatabaseConnectivityErrorTaxonomy {
20
21 /** @var array<int, string> */
22 private const COMMANDS_OUT_OF_SYNC_MARKERS = array(
23 'commands out of sync',
24 'cr_commands_out_of_sync',
25 'errno 2014',
26 'errno: 2014',
27 'error 2014:',
28 '[2014]',
29 '(2014)',
30 );
31
32 /** @var array<int, string> */
33 private const DEADLOCK_OR_LOCK_TIMEOUT_MARKERS = array(
34 'deadlock found',
35 'lock wait timeout exceeded',
36 'lock deadlock; retry transaction',
37 'error 1213',
38 'error 1205',
39 );
40
41 /** @var ABJ_404_Solution_Functions */
42 private $f;
43
44 /**
45 * @param ABJ_404_Solution_Functions $functions
46 */
47 public function __construct($functions) {
48 $this->f = $functions;
49 }
50
51 /** @param string|null $errorText @return bool */
52 public function isTransientConnectionError(?string $errorText): bool {
53 $errorText = $errorText ?? '';
54 if ($errorText === '') {
55 return false;
56 }
57 $lower = strtolower($errorText);
58 $transientMarkers = array(
59 'server has gone away',
60 'lost connection to mysql server',
61 'error while sending query packet',
62 'packets out of order',
63 'connection was killed',
64 );
65 foreach ($transientMarkers as $marker) {
66 if ($this->f->strpos($lower, $marker) !== false) {
67 return true;
68 }
69 }
70 foreach (array('2006', '2013', '2055') as $code) {
71 if ($this->f->strpos($lower, '[' . $code . ']') !== false
72 || $this->f->strpos($lower, '(' . $code . ')') !== false
73 || $this->f->strpos($lower, 'errno ' . $code) !== false
74 || $this->f->strpos($lower, 'errno: ' . $code) !== false
75 || $this->f->strpos($lower, 'error: ' . $code . ' ') !== false
76 || $this->f->strpos($lower, 'error ' . $code . ':') !== false) {
77 return true;
78 }
79 }
80 return false;
81 }
82
83 /** @param string $errorText @return bool */
84 public function isQueryTimeoutError(string $errorText): bool {
85 if ($errorText === '') {
86 return false;
87 }
88 return (strpos($errorText, '3024') !== false ||
89 strpos($errorText, '1969') !== false ||
90 stripos($errorText, 'max_execution_time') !== false ||
91 stripos($errorText, 'max_statement_time') !== false);
92 }
93
94 /** @param string $errorText @return bool */
95 public function isPacketTooLarge(string $errorText): bool {
96 if ($errorText === '') {
97 return false;
98 }
99 $lower = strtolower($errorText);
100 return ($this->f->strpos($lower, 'max_allowed_packet') !== false ||
101 $this->f->strpos($lower, 'got a packet bigger') !== false ||
102 $this->f->strpos($lower, '1153') !== false);
103 }
104
105 /** @param string $errorText @return bool */
106 public function isDeadlockOrLockTimeoutError(string $errorText): bool {
107 if ($errorText === '') {
108 return false;
109 }
110 $lower = strtolower($errorText);
111 foreach (self::DEADLOCK_OR_LOCK_TIMEOUT_MARKERS as $marker) {
112 if ($this->f->strpos($lower, $marker) !== false) {
113 return true;
114 }
115 }
116 return false;
117 }
118
119 /** @param string $errorText @return bool */
120 public function isCommandsOutOfSyncError(string $errorText): bool {
121 if ($errorText === '') {
122 return false;
123 }
124 $lower = strtolower($errorText);
125 foreach (self::COMMANDS_OUT_OF_SYNC_MARKERS as $marker) {
126 if ($this->f->strpos($lower, $marker) !== false) {
127 return true;
128 }
129 }
130 return false;
131 }
132 }
133