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 / DatabaseInfrastructureErrorTaxonomy.php

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

131 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) {
3 exit;
4 }
5
6 /**
7 * Composite database infrastructure error taxonomy.
8 *
9 * Holds three focused subsystem taxonomies and exposes them via accessor
10 * methods. Owns no classification logic of its own; the union aggregator
11 * `isInfrastructureSqlError()` is the only behavior at this layer.
12 *
13 * connectivity() - transport, timeout, packet, deadlock failures
14 * (DatabaseConnectivityErrorTaxonomy)
15 * hostState() - disk, quota, read-only, oom, access, galera,
16 * set-statement privilege failures
17 * (DatabaseHostStateErrorTaxonomy)
18 * schema() - crashed/missing tables, view-build churn, invalid
19 * data, collation failures
20 * (DatabaseSchemaErrorTaxonomy)
21 *
22 * No database, transient, notice, or logging side effects.
23 */
24
25 require_once __DIR__ . '/DatabaseConnectivityErrorTaxonomy.php';
26 require_once __DIR__ . '/DatabaseHostStateErrorTaxonomy.php';
27 require_once __DIR__ . '/DatabaseSchemaErrorTaxonomy.php';
28
29 // allow-no-test-found: covered through DatabaseErrorClassifier facade by tests/SuppressWpdbErrorsTest.php and tests/DataAccessRetrySemanticsTest.php / tests/DataAccessInfraErrorNoticeLifecycleTest.php
30 class ABJ_404_Solution_DatabaseInfrastructureErrorTaxonomy {
31
32 public const QUERY_RETRY_NONE = 'none';
33 public const QUERY_RETRY_IMMEDIATE = 'immediate';
34 public const QUERY_RETRY_BACKOFF = 'backoff';
35
36 /** @var ABJ_404_Solution_DatabaseConnectivityErrorTaxonomy */
37 private $connectivity;
38
39 /** @var ABJ_404_Solution_DatabaseHostStateErrorTaxonomy */
40 private $hostState;
41
42 /** @var ABJ_404_Solution_DatabaseSchemaErrorTaxonomy */
43 private $schema;
44
45 /**
46 * @param ABJ_404_Solution_Functions $functions
47 */
48 public function __construct($functions) {
49 $this->connectivity = new ABJ_404_Solution_DatabaseConnectivityErrorTaxonomy($functions);
50 $this->hostState = new ABJ_404_Solution_DatabaseHostStateErrorTaxonomy($functions);
51 $this->schema = new ABJ_404_Solution_DatabaseSchemaErrorTaxonomy($functions);
52 }
53
54 /** @return ABJ_404_Solution_DatabaseConnectivityErrorTaxonomy */
55 public function connectivity(): ABJ_404_Solution_DatabaseConnectivityErrorTaxonomy {
56 return $this->connectivity;
57 }
58
59 /** @return ABJ_404_Solution_DatabaseHostStateErrorTaxonomy */
60 public function hostState(): ABJ_404_Solution_DatabaseHostStateErrorTaxonomy {
61 return $this->hostState;
62 }
63
64 /** @return ABJ_404_Solution_DatabaseSchemaErrorTaxonomy */
65 public function schema(): ABJ_404_Solution_DatabaseSchemaErrorTaxonomy {
66 return $this->schema;
67 }
68
69 /**
70 * Union aggregator: true when the error text matches any infrastructure
71 * failure mode the plugin should react to (notice-state, retry, repair,
72 * or write-block).
73 *
74 * @param string $errorText
75 * @return bool
76 */
77 public function isInfrastructureSqlError(string $errorText): bool {
78 return $this->hostState->isDiskFullError($errorText)
79 || $this->hostState->isReadOnlyError($errorText)
80 || $this->hostState->isQuotaLimitError($errorText)
81 || $this->hostState->isOutOfMemoryError($errorText)
82 || $this->schema->isInvalidDataError($errorText)
83 || $this->schema->isCollationError($errorText)
84 || $this->schema->isMissingPluginTableError($errorText)
85 || $this->schema->isIncorrectKeyFileError($errorText)
86 || $this->schema->isCrashedTableError($errorText)
87 || $this->connectivity->isDeadlockOrLockTimeoutError($errorText)
88 || $this->hostState->isGaleraConflictError($errorText)
89 || $this->connectivity->isTransientConnectionError($errorText)
90 || $this->connectivity->isQueryTimeoutError($errorText)
91 || $this->connectivity->isCommandsOutOfSyncError($errorText)
92 || $this->hostState->isAccessDeniedError($errorText);
93 }
94
95 /**
96 * Classify retryable DAO errors once so observed-error suppression and the
97 * recovery pipeline cannot drift into different string-family policies.
98 *
99 * @param string $errorText
100 * @return array{strategy: string, branch: string, reason: string}
101 */
102 public function classifyQueryRetry(string $errorText): array {
103 if ($this->connectivity->isTransientConnectionError($errorText)) {
104 return array(
105 'strategy' => self::QUERY_RETRY_IMMEDIATE,
106 'branch' => 'transient_connection',
107 'reason' => 'connection_lost',
108 );
109 }
110 if ($this->hostState->isGaleraConflictError($errorText)) {
111 return array(
112 'strategy' => self::QUERY_RETRY_IMMEDIATE,
113 'branch' => 'galera_cluster_state',
114 'reason' => 'galera_retryable',
115 );
116 }
117 if ($this->connectivity->isDeadlockOrLockTimeoutError($errorText)) {
118 return array(
119 'strategy' => self::QUERY_RETRY_BACKOFF,
120 'branch' => 'deadlock',
121 'reason' => 'deadlock_or_lock_timeout',
122 );
123 }
124 return array(
125 'strategy' => self::QUERY_RETRY_NONE,
126 'branch' => '',
127 'reason' => '',
128 );
129 }
130 }
131