config = [ 'host' => $_ENV['DB_HOST'] ?? 'localhost', 'port' => $_ENV['DB_PORT'] ?? '3306', 'name' => $_ENV['DB_NAME'] ?? 'bot', 'user' => $_ENV['DB_USER'] ?? 'nickpons666', 'pass' => $_ENV['DB_PASS'] ?? 'MiPo6425@@', 'charset' => 'utf8mb4', 'timeout' => 30, // Tiempo de espera de conexión en segundos 'reconnect_attempts' => 3, // Número de intentos de reconexión 'reconnect_delay' => 1, // Tiempo de espera entre reconexiones en segundos ]; $this->connect(); } public static function getInstance() { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } public function getConnection() { // Verificar si la conexión sigue activa try { $this->pdo->query('SELECT 1'); return $this->pdo; } catch (PDOException $e) { // Si la conexión se perdió, intentar reconectar error_log("La conexión a la base de datos se perdió. Intentando reconectar..."); $this->connect(); return $this->pdo; } } private function connect() { $dsn = sprintf( 'mysql:host=%s;port=%s;dbname=%s;charset=%s', $this->config['host'], $this->config['port'], $this->config['name'], $this->config['charset'] ); $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_TIMEOUT => $this->config['timeout'], PDO::ATTR_PERSISTENT => false, // No usar conexiones persistentes para evitar problemas PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci" ]; $attempts = 0; $lastException = null; while ($attempts < $this->config['reconnect_attempts']) { try { $this->pdo = new PDO( $dsn, $this->config['user'], $this->config['pass'], $options ); // Configuración adicional de la conexión $this->pdo->exec("SET time_zone = '-06:00';"); $this->pdo->exec("SET SESSION wait_timeout=28800;"); // 8 horas $this->pdo->exec("SET SESSION interactive_timeout=28800;"); // 8 horas error_log("Conexión a la base de datos establecida correctamente."); return; } catch (PDOException $e) { $lastException = $e; $attempts++; error_log(sprintf( "Intento de conexión %d fallido: %s. Reintentando en %d segundos...", $attempts, $e->getMessage(), $this->config['reconnect_delay'] )); if ($attempts < $this->config['reconnect_attempts']) { sleep($this->config['reconnect_delay']); } } } // Si llegamos aquí, todos los intentos fallaron error_log("No se pudo establecer la conexión después de {$this->config['reconnect_attempts']} intentos."); throw $lastException; } } // Crear una instancia de la conexión try { $pdo = DatabaseConnection::getInstance()->getConnection(); } catch (PDOException $e) { error_log("Error crítico de conexión a la base de datos: " . $e->getMessage()); // No usar die() aquí porque mata a los workers - dejar que el código maneje el error // Para scripts web, el error se mostrará en el log y el script continuará // Para workers, pueden manejar la excepción y reintentar if (php_sapi_name() !== 'cli') { // Solo para contexto web die("Error de conexión a la base de datos. Por favor, inténtalo de nuevo más tarde."); } // Para CLI (workers), lanzar la excepción para que el worker la maneje throw $e; } ?>