Files

126 lines
4.6 KiB
PHP
Executable File

<?php
require_once __DIR__ . '/../config/config.php';
// Establecer la zona horaria predeterminada
date_default_timezone_set('America/Mexico_City');
/**
* Clase para manejar la conexión a la base de datos con reconexión automática
*/
class DatabaseConnection {
private static $instance = null;
private $pdo = null;
private $config = [];
private function __construct() {
$this->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;
}
?>