queryScalar('SELECT 1'); $responseTime = (microtime(true) - $startTime) * 1000; // in Millisekunden if ($result != 1) { return HealthCheckResult::unhealthy( $responseTime, 'Unexpected result from health check query', null, ['expected' => 1, 'actual' => $result] ); } return HealthCheckResult::healthy($responseTime, 'Connection is healthy'); } catch (\Throwable $e) { $responseTime = (microtime(true) - $startTime) * 1000; return HealthCheckResult::error($e, $responseTime); } } /** * Führt einen Health Check mit Timeout aus */ public function checkHealthWithTimeout(ConnectionInterface $connection): HealthCheckResult { $startTime = time(); while ((time() - $startTime) < $this->timeoutSeconds) { $result = $this->checkHealth($connection); if ($result->isHealthy) { return $result; } // Kurz warten vor nächstem Versuch $this->timer->sleep(Duration::fromMilliseconds(100)); } return HealthCheckResult::timeout($this->timeoutSeconds * 1000); } /** * Führt erweiterte Health Checks aus */ public function checkDetailedHealth(ConnectionInterface $connection): HealthCheckResult { $startTime = microtime(true); $additionalData = []; try { // 1. Basis Health Check $basicResult = $this->checkHealth($connection); if (! $basicResult->isHealthy) { return $basicResult; } $additionalData['basic_check'] = $basicResult->toArray(); // 2. PDO-Status prüfen $pdoStatus = $this->checkPdoStatus($connection); $additionalData['pdo_status'] = $pdoStatus; // 3. Custom Queries ausführen if (! empty($this->customQueries)) { $customResults = $this->executeCustomQueries($connection); $additionalData['custom_queries'] = $customResults; } // 4. Connection Attributes prüfen $attributes = $this->getConnectionAttributes($connection); $additionalData['connection_attributes'] = $attributes; $responseTime = (microtime(true) - $startTime) * 1000; return HealthCheckResult::healthy( $responseTime, 'Detailed health check passed', $additionalData ); } catch (\Throwable $e) { $responseTime = (microtime(true) - $startTime) * 1000; return HealthCheckResult::error($e, $responseTime)->withAdditionalData('partial_data', $additionalData); } } /** * Prüft ob die Connection noch lebendig ist (schneller Check) */ public function checkConnectionAlive(ConnectionInterface $connection): bool { try { $pdo = $connection->getPdo(); // Prüfe ob die PDO-Verbindung noch aktiv ist $stmt = $pdo->query('SELECT 1'); return $stmt !== false; } catch (\Throwable) { return false; } } /** * Prüft den PDO-Status */ private function checkPdoStatus(ConnectionInterface $connection): array { try { $pdo = $connection->getPdo(); return [ 'connection_status' => $pdo->getAttribute(\PDO::ATTR_CONNECTION_STATUS), 'server_info' => $pdo->getAttribute(\PDO::ATTR_SERVER_INFO), 'driver_name' => $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME), 'client_version' => $pdo->getAttribute(\PDO::ATTR_CLIENT_VERSION), 'server_version' => $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), 'in_transaction' => $connection->inTransaction(), ]; } catch (\Throwable $e) { return ['error' => $e->getMessage()]; } } /** * Führt benutzerdefinierte Queries aus */ private function executeCustomQueries(ConnectionInterface $connection): array { $results = []; foreach ($this->customQueries as $name => $query) { try { $startTime = microtime(true); $result = $connection->queryScalar($query); $responseTime = (microtime(true) - $startTime) * 1000; $results[$name] = [ 'success' => true, 'result' => $result, 'response_time_ms' => round($responseTime, 2), ]; } catch (\Throwable $e) { $results[$name] = [ 'success' => false, 'error' => $e->getMessage(), 'response_time_ms' => 0, ]; } } return $results; } /** * Sammelt Connection-Attribute */ private function getConnectionAttributes(ConnectionInterface $connection): array { try { $pdo = $connection->getPdo(); $attributes = []; $attributesToCheck = [ 'AUTOCOMMIT' => \PDO::ATTR_AUTOCOMMIT, 'ERRMODE' => \PDO::ATTR_ERRMODE, 'CASE' => \PDO::ATTR_CASE, 'NULL_TO_STRING' => \PDO::ATTR_NULL_TO_STRING, 'STRINGIFY_FETCHES' => \PDO::ATTR_STRINGIFY_FETCHES, 'STATEMENT_CLASS' => \PDO::ATTR_STATEMENT_CLASS, 'TIMEOUT' => \PDO::ATTR_TIMEOUT, 'EMULATE_PREPARES' => \PDO::ATTR_EMULATE_PREPARES, 'DEFAULT_FETCH_MODE' => \PDO::ATTR_DEFAULT_FETCH_MODE, ]; foreach ($attributesToCheck as $name => $constant) { try { $attributes[$name] = $pdo->getAttribute($constant); } catch (\Throwable) { $attributes[$name] = 'Not supported'; } } return $attributes; } catch (\Throwable $e) { return ['error' => $e->getMessage()]; } } /** * Factory-Methoden für verschiedene Health Check-Konfigurationen */ public static function quick(?Timer $timer = null, int $timeoutSeconds = 2): self { return new self($timer ?? new SystemTimer(), $timeoutSeconds); } public static function detailed(?Timer $timer = null, int $timeoutSeconds = 10, array $customQueries = []): self { return new self($timer ?? new SystemTimer(), $timeoutSeconds, $customQueries); } public static function withCustomQueries(array $customQueries, ?Timer $timer = null, int $timeoutSeconds = 5): self { return new self($timer ?? new SystemTimer(), $timeoutSeconds, $customQueries); } }