modified: app.py

modified:   bot.py
This commit is contained in:
SimolZimol
2025-08-24 01:27:11 +02:00
parent 02dcde6f54
commit eb4ea0f6b8
2 changed files with 82 additions and 26 deletions

80
app.py
View File

@@ -7,6 +7,7 @@ from requests_oauthlib import OAuth2Session
import os
import subprocess
import psutil
import time
import mysql.connector
import mysql.connector.pooling
from datetime import datetime, timedelta
@@ -89,7 +90,7 @@ def stop_bot():
# Database Connection Pool für bessere Verbindungsverwaltung
app_pool = mysql.connector.pooling.MySQLConnectionPool(
pool_name="app_pool",
pool_size=15, # Reduziert von 20 auf 15 (Bot: 30, App: 15 = max 45 statt 50+)
pool_size=8, # Stark reduziert von 15 auf 8 (Bot: 25, App: 8 = 33 total)
pool_reset_session=True,
host=DB_HOST,
port=DB_PORT,
@@ -109,14 +110,24 @@ def get_db_connection():
return connection
except mysql.connector.PoolError as e:
print(f"Pool error in app.py: {e}")
# Fallback zu direkter Verbindung bei Pool-Problemen
# Besserer Fallback mit Retry-Mechanismus
for attempt in range(3):
try:
print(f"Attempting direct connection (attempt {attempt + 1}/3)")
return mysql.connector.connect(
host=DB_HOST,
port=DB_PORT,
user=DB_USER,
password=DB_PASS,
database=DB_NAME
database=DB_NAME,
connect_timeout=5,
autocommit=True
)
except Exception as retry_error:
print(f"Direct connection attempt {attempt + 1} failed: {retry_error}")
if attempt == 2: # Letzter Versuch
raise retry_error
time.sleep(1) # Kurze Pause zwischen Versuchen
from contextlib import contextmanager
@@ -231,6 +242,24 @@ def landing_page():
"""Landing Page"""
return render_template("landing.html")
@app.route("/db_status")
def db_status():
"""Debug-Route für DB-Pool Status"""
try:
status = get_pool_status()
with get_db_cursor() as (cursor, connection):
cursor.execute("SELECT 1")
db_ok = True
except Exception as e:
status = {"error": str(e)}
db_ok = False
return jsonify({
"pool_status": status,
"database_ok": db_ok,
"timestamp": datetime.now().isoformat()
})
@app.route("/about")
def about():
"""Öffentliche Über-uns-Seite"""
@@ -268,29 +297,56 @@ def load_user_data():
g.is_admin = session.get("is_admin", False)
g.bot_running = bot_status() # Lädt den Bot-Status in g
# Hole die Liste der Gilden aus der Datenbank
connection = get_db_connection()
cursor = connection.cursor(dictionary=True)
# Lade die Gilden des Nutzers
# Lade die Gilden des Nutzers aus der Session (ohne DB-Zugriff)
user_guilds = session.get("discord_guilds", [])
# Nur DB-Zugriff wenn Gilden-Daten nicht im Cache sind
guild_cache_key = f"guild_cache_{g.user_info['id']}"
if guild_cache_key not in session or not session[guild_cache_key]:
try:
with get_db_cursor() as (cursor, connection):
user_guild_ids = [guild["id"] for guild in user_guilds]
if user_guild_ids: # Nur wenn Gilden existieren
# Finde nur die Gilden, die auch in der Datenbank existieren
cursor.execute("SELECT guild_id FROM guilds WHERE guild_id IN (%s)" % ','.join(['%s'] * len(user_guild_ids)), user_guild_ids)
placeholders = ','.join(['%s'] * len(user_guild_ids))
cursor.execute(f"SELECT guild_id FROM guilds WHERE guild_id IN ({placeholders})", user_guild_ids)
existing_guilds = cursor.fetchall()
existing_guild_ids = {g["guild_id"] for g in existing_guilds}
# Filtere die Gilden des Nutzers basierend auf der Existenz in der Datenbank
g.guilds = [guild for guild in user_guilds if int(guild["id"]) in {g["guild_id"] for g in existing_guilds}]
filtered_guilds = [guild for guild in user_guilds if int(guild["id"]) in existing_guild_ids]
cursor.close()
connection.close()
# Cache die gefilterten Gilden für 5 Minuten
session[guild_cache_key] = filtered_guilds
session[f"{guild_cache_key}_time"] = time.time()
g.guilds = filtered_guilds
else:
g.guilds = []
except Exception as e:
print(f"Error loading guild data: {e}")
# Fallback: Verwende alle Gilden aus der Session
g.guilds = user_guilds
# Setze einen Flag für DB-Probleme
g.db_error = True
else:
# Prüfe Cache-Alter (5 Minuten TTL)
cache_time = session.get(f"{guild_cache_key}_time", 0)
if time.time() - cache_time > 300: # 5 Minuten
# Cache ist abgelaufen, lösche ihn
session.pop(guild_cache_key, None)
session.pop(f"{guild_cache_key}_time", None)
g.guilds = user_guilds # Fallback
else:
# Verwende gecachte Daten
g.guilds = session[guild_cache_key]
else:
# Falls der Benutzer nicht eingeloggt ist, keine Daten setzen
g.user_info = None
g.is_admin = False
g.guilds = []
g.bot_running = False
g.db_error = False
@app.route("/callback")
def callback():

2
bot.py
View File

@@ -196,7 +196,7 @@ def retry_query(func, *args, retries=3, delay=5):
pool = mysql.connector.pooling.MySQLConnectionPool(
pool_name="mypool",
pool_size=25, # Reduziert von 30 auf 25 (App: 15, Bot: 25 = 40 total)
pool_size=15, # Weiter reduziert von 25 auf 15 (App: 8, Bot: 15 = 23 total)
pool_reset_session=True,
autocommit=True,
host=DB_HOST,