modified: app.py
modified: bot.py
This commit is contained in:
80
app.py
80
app.py
@@ -7,6 +7,7 @@ from requests_oauthlib import OAuth2Session
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import psutil
|
import psutil
|
||||||
|
import time
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
import mysql.connector.pooling
|
import mysql.connector.pooling
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
@@ -89,7 +90,7 @@ def stop_bot():
|
|||||||
# Database Connection Pool für bessere Verbindungsverwaltung
|
# Database Connection Pool für bessere Verbindungsverwaltung
|
||||||
app_pool = mysql.connector.pooling.MySQLConnectionPool(
|
app_pool = mysql.connector.pooling.MySQLConnectionPool(
|
||||||
pool_name="app_pool",
|
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,
|
pool_reset_session=True,
|
||||||
host=DB_HOST,
|
host=DB_HOST,
|
||||||
port=DB_PORT,
|
port=DB_PORT,
|
||||||
@@ -109,14 +110,24 @@ def get_db_connection():
|
|||||||
return connection
|
return connection
|
||||||
except mysql.connector.PoolError as e:
|
except mysql.connector.PoolError as e:
|
||||||
print(f"Pool error in app.py: {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(
|
return mysql.connector.connect(
|
||||||
host=DB_HOST,
|
host=DB_HOST,
|
||||||
port=DB_PORT,
|
port=DB_PORT,
|
||||||
user=DB_USER,
|
user=DB_USER,
|
||||||
password=DB_PASS,
|
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
|
from contextlib import contextmanager
|
||||||
|
|
||||||
@@ -231,6 +242,24 @@ def landing_page():
|
|||||||
"""Landing Page"""
|
"""Landing Page"""
|
||||||
return render_template("landing.html")
|
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")
|
@app.route("/about")
|
||||||
def about():
|
def about():
|
||||||
"""Öffentliche Über-uns-Seite"""
|
"""Öffentliche Über-uns-Seite"""
|
||||||
@@ -268,29 +297,56 @@ def load_user_data():
|
|||||||
g.is_admin = session.get("is_admin", False)
|
g.is_admin = session.get("is_admin", False)
|
||||||
g.bot_running = bot_status() # Lädt den Bot-Status in g
|
g.bot_running = bot_status() # Lädt den Bot-Status in g
|
||||||
|
|
||||||
# Hole die Liste der Gilden aus der Datenbank
|
# Lade die Gilden des Nutzers aus der Session (ohne DB-Zugriff)
|
||||||
connection = get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
# Lade die Gilden des Nutzers
|
|
||||||
user_guilds = session.get("discord_guilds", [])
|
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]
|
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
|
# 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_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
|
# 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()
|
# Cache die gefilterten Gilden für 5 Minuten
|
||||||
connection.close()
|
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:
|
else:
|
||||||
# Falls der Benutzer nicht eingeloggt ist, keine Daten setzen
|
# Falls der Benutzer nicht eingeloggt ist, keine Daten setzen
|
||||||
g.user_info = None
|
g.user_info = None
|
||||||
g.is_admin = False
|
g.is_admin = False
|
||||||
g.guilds = []
|
g.guilds = []
|
||||||
g.bot_running = False
|
g.bot_running = False
|
||||||
|
g.db_error = False
|
||||||
|
|
||||||
@app.route("/callback")
|
@app.route("/callback")
|
||||||
def callback():
|
def callback():
|
||||||
|
|||||||
2
bot.py
2
bot.py
@@ -196,7 +196,7 @@ def retry_query(func, *args, retries=3, delay=5):
|
|||||||
|
|
||||||
pool = mysql.connector.pooling.MySQLConnectionPool(
|
pool = mysql.connector.pooling.MySQLConnectionPool(
|
||||||
pool_name="mypool",
|
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,
|
pool_reset_session=True,
|
||||||
autocommit=True,
|
autocommit=True,
|
||||||
host=DB_HOST,
|
host=DB_HOST,
|
||||||
|
|||||||
Reference in New Issue
Block a user