From ae51b6333ca8de85c166736fcda817eee2042d8e Mon Sep 17 00:00:00 2001 From: nickpons666 Date: Fri, 20 Mar 2026 03:55:22 -0600 Subject: [PATCH] =?UTF-8?q?fix:=20A=C3=B1adir=20reintentos=20de=20conexi?= =?UTF-8?q?=C3=B3n=20MySQL=20y=20limitar=20reinicios=20de=20servicios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - get_connection() reintenta hasta 30 veces con delays de 2s - iniciar_todo.py limita reinicios a 3 por servicio con cooldown de 60s - Evitar loops infinitos cuando MySQL no está disponible --- botdiscord/database.py | 73 ++++++++++++++++++++++++++---------------- iniciar_todo.py | 30 +++++++++++++++-- 2 files changed, 72 insertions(+), 31 deletions(-) diff --git a/botdiscord/database.py b/botdiscord/database.py index 18549cd..f6e1b96 100644 --- a/botdiscord/database.py +++ b/botdiscord/database.py @@ -1,10 +1,13 @@ import sqlite3 import mysql.connector import json +import time from mysql.connector import Error as MySQLError from botdiscord.config import get_db_config, get_db_type _connection = None +MAX_CONNECTION_RETRIES = 30 +CONNECTION_RETRY_DELAY = 2 def get_connection(): global _connection @@ -13,39 +16,53 @@ def get_connection(): if db_type == "mysql": db_config = get_db_config() - # Si no hay conexión o no está activa, intentamos conectar/reconectar if _connection is None: - try: - _connection = mysql.connector.connect( - host=db_config.get("host"), - port=db_config.get("port"), - user=db_config.get("user"), - password=db_config.get("password"), - database=db_config.get("name"), - consume_results=True, - connection_timeout=5 - ) - except MySQLError as e: - print(f"CRITICAL: Could not establish initial MySQL connection: {e}") - raise + for attempt in range(1, MAX_CONNECTION_RETRIES + 1): + try: + _connection = mysql.connector.connect( + host=db_config.get("host"), + port=db_config.get("port"), + user=db_config.get("user"), + password=db_config.get("password"), + database=db_config.get("name"), + consume_results=True, + connection_timeout=10 + ) + print(f"[DB] MySQL conectado exitosamente") + break + except MySQLError as e: + if attempt < MAX_CONNECTION_RETRIES: + print(f"[DB] Intento {attempt}/{MAX_CONNECTION_RETRIES}: MySQL no disponible, reintentando en {CONNECTION_RETRY_DELAY}s...") + time.sleep(CONNECTION_RETRY_DELAY) + _connection = None + else: + print(f"[DB] CRITICAL: No se pudo conectar a MySQL después de {MAX_CONNECTION_RETRIES} intentos") + raise - # Verificar salud de la conexión existente try: _connection.ping(reconnect=True, attempts=3, delay=1) except MySQLError: - try: - _connection = mysql.connector.connect( - host=db_config.get("host"), - port=db_config.get("port"), - user=db_config.get("user"), - password=db_config.get("password"), - database=db_config.get("name"), - consume_results=True, - connection_timeout=5 - ) - except MySQLError as e: - print(f"CRITICAL: MySQL reconnection failed: {e}") - raise + for attempt in range(1, 6): + try: + print(f"[DB] Reconectando a MySQL (intento {attempt}/5)...") + _connection = mysql.connector.connect( + host=db_config.get("host"), + port=db_config.get("port"), + user=db_config.get("user"), + password=db_config.get("password"), + database=db_config.get("name"), + consume_results=True, + connection_timeout=10 + ) + print(f"[DB] MySQL reconectado exitosamente") + break + except MySQLError as e: + if attempt < 5: + time.sleep(2) + _connection = None + else: + print(f"[DB] CRITICAL: MySQL reconnection failed: {e}") + raise return _connection else: diff --git a/iniciar_todo.py b/iniciar_todo.py index 368ac1c..9e3bd45 100755 --- a/iniciar_todo.py +++ b/iniciar_todo.py @@ -25,6 +25,9 @@ print("🤖 Iniciando Bots de Traducción...") print("=" * 40) processes = [] +restart_counts = {} +MAX_RESTARTS = 3 +RESTART_COOLDOWN = 60 def start_process(cmd, name, delay_before=0): if delay_before > 0: @@ -72,11 +75,32 @@ signal.signal(signal.SIGTERM, signal_handler) while True: for p, name in processes: if p.poll() is not None: - log(f"⚠️ {name} se detuvo, reiniciando...") + if name not in restart_counts: + restart_counts[name] = {"count": 0, "last_restart": 0} + + current_time = time.time() + + if current_time - restart_counts[name]["last_restart"] > RESTART_COOLDOWN: + restart_counts[name]["count"] = 0 + + restart_counts[name]["count"] += 1 + restart_counts[name]["last_restart"] = current_time + + if restart_counts[name]["count"] > MAX_RESTARTS: + log(f"⛔ {name} se detuvo {restart_counts[name]['count']} veces. Demasiados reinicios. Esperando {RESTART_COOLDOWN}s...") + time.sleep(RESTART_COOLDOWN) + restart_counts[name]["count"] = 0 + continue + + log(f"⚠️ {name} se detuvo (intento {restart_counts[name]['count']}/{MAX_RESTARTS}), reiniciando...") + + delay = 5 if name != "Discord Bot" else 10 + if name == "Discord Bot": - p1 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "botdiscord/bot.py"], "Discord Bot", delay_before=10) + p1 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "botdiscord/bot.py"], "Discord Bot", delay_before=delay) elif name == "Telegram Bot": - p2 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "bottelegram/telegram_bot.py"], "Telegram Bot", delay_before=5) + p2 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "bottelegram/telegram_bot.py"], "Telegram Bot", delay_before=delay) elif name == "Panel Web": p3 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "panel/main.py"], "Panel Web", delay_before=0) + time.sleep(5)