📝 "Refactor backend

This commit is contained in:
2025-05-31 23:44:20 +02:00
parent f5a39a450a
commit 831caec87a
11 changed files with 1828 additions and 22 deletions

View File

@ -4828,34 +4828,32 @@ def session_status():
@app.route('/api/session/extend', methods=['POST'])
@login_required
def extend_session():
"""
Verlängert die aktuelle Session um weitere Zeit.
"""
"""Verlängert die aktuelle Session um die Standard-Lebensdauer"""
try:
data = request.get_json() or {}
extend_minutes = data.get('extend_minutes', 30)
# Session-Lebensdauer zurücksetzen
session.permanent = True
# Begrenzen der Verlängerung (max 2 Stunden)
extend_minutes = min(extend_minutes, 120)
# Aktivität für Rate Limiting aktualisieren
current_user.update_last_activity()
now = datetime.now()
session['last_activity'] = now.isoformat()
session['session_extended'] = now.isoformat()
session['extended_by_minutes'] = extend_minutes
# Optional: Session-Statistiken für Admin
user_agent = request.headers.get('User-Agent', 'Unknown')
ip_address = request.environ.get('HTTP_X_FORWARDED_FOR', request.remote_addr)
auth_logger.info(f"🕒 Session verlängert für Benutzer {current_user.email} um {extend_minutes} Minuten")
app_logger.info(f"Session verlängert für User {current_user.id} (IP: {ip_address})")
return jsonify({
"success": True,
"message": f"Session um {extend_minutes} Minuten verlängert",
"extended_until": (now + timedelta(minutes=extend_minutes)).isoformat(),
"extended_minutes": extend_minutes
'success': True,
'message': 'Session erfolgreich verlängert',
'expires_at': (datetime.now() + SESSION_LIFETIME).isoformat()
})
except Exception as e:
auth_logger.error(f"Fehler beim Verlängern der Session: {str(e)}")
return jsonify({"error": "Session-Verlängerung fehlgeschlagen"}), 500
app_logger.error(f"Fehler beim Verlängern der Session: {str(e)}")
return jsonify({
'success': False,
'error': 'Fehler beim Verlängern der Session'
}), 500
# ===== GASTANTRÄGE API-ROUTEN =====
@ -5668,4 +5666,274 @@ if __name__ == "__main__":
stop_queue_manager()
except:
pass
sys.exit(1)
sys.exit(1)
# ===== AUTO-OPTIMIERUNG-API-ENDPUNKTE =====
@app.route('/api/optimization/auto-optimize', methods=['POST'])
@login_required
def auto_optimize_jobs():
"""
Automatische Optimierung der Druckaufträge durchführen
Implementiert intelligente Job-Verteilung basierend auf verschiedenen Algorithmen
"""
try:
data = request.get_json()
settings = data.get('settings', {})
enabled = data.get('enabled', False)
db_session = get_db_session()
# Aktuelle Jobs in der Warteschlange abrufen
pending_jobs = db_session.query(Job).filter(
Job.status.in_(['queued', 'pending'])
).all()
if not pending_jobs:
db_session.close()
return jsonify({
'success': True,
'message': 'Keine Jobs zur Optimierung verfügbar',
'optimized_jobs': 0
})
# Verfügbare Drucker abrufen
available_printers = db_session.query(Printer).filter(Printer.active == True).all()
if not available_printers:
db_session.close()
return jsonify({
'success': False,
'error': 'Keine verfügbaren Drucker für Optimierung'
})
# Optimierungs-Algorithmus anwenden
algorithm = settings.get('algorithm', 'round_robin')
optimized_count = 0
if algorithm == 'round_robin':
optimized_count = apply_round_robin_optimization(pending_jobs, available_printers, db_session)
elif algorithm == 'load_balance':
optimized_count = apply_load_balance_optimization(pending_jobs, available_printers, db_session)
elif algorithm == 'priority_based':
optimized_count = apply_priority_optimization(pending_jobs, available_printers, db_session)
db_session.commit()
jobs_logger.info(f"Auto-Optimierung durchgeführt: {optimized_count} Jobs optimiert mit Algorithmus {algorithm}")
# System-Log erstellen
log_entry = SystemLog(
level='INFO',
component='optimization',
message=f'Auto-Optimierung durchgeführt: {optimized_count} Jobs optimiert',
user_id=current_user.id if current_user.is_authenticated else None,
details=json.dumps({
'algorithm': algorithm,
'optimized_jobs': optimized_count,
'settings': settings
})
)
db_session.add(log_entry)
db_session.commit()
db_session.close()
return jsonify({
'success': True,
'optimized_jobs': optimized_count,
'algorithm': algorithm,
'message': f'Optimierung erfolgreich: {optimized_count} Jobs wurden optimiert'
})
except Exception as e:
app_logger.error(f"Fehler bei der Auto-Optimierung: {str(e)}")
return jsonify({
'success': False,
'error': f'Optimierung fehlgeschlagen: {str(e)}'
}), 500
@app.route('/api/optimization/settings', methods=['GET', 'POST'])
@login_required
def optimization_settings():
"""Optimierungs-Einstellungen abrufen und speichern"""
db_session = get_db_session()
if request.method == 'GET':
try:
# Standard-Einstellungen oder benutzerdefinierte laden
default_settings = {
'algorithm': 'round_robin',
'consider_distance': True,
'minimize_changeover': True,
'max_batch_size': 10,
'time_window': 24,
'auto_optimization_enabled': False
}
# Benutzereinstellungen aus der Session laden oder Standardwerte verwenden
user_settings = session.get('user_settings', {})
optimization_settings = user_settings.get('optimization', default_settings)
# Sicherstellen, dass alle erforderlichen Schlüssel vorhanden sind
for key, value in default_settings.items():
if key not in optimization_settings:
optimization_settings[key] = value
return jsonify({
'success': True,
'settings': optimization_settings
})
except Exception as e:
app_logger.error(f"Fehler beim Abrufen der Optimierungs-Einstellungen: {str(e)}")
return jsonify({
'success': False,
'error': 'Fehler beim Laden der Einstellungen'
}), 500
elif request.method == 'POST':
try:
settings = request.get_json()
# Validierung der Einstellungen
if not validate_optimization_settings(settings):
return jsonify({
'success': False,
'error': 'Ungültige Optimierungs-Einstellungen'
}), 400
# Einstellungen in der Session speichern
user_settings = session.get('user_settings', {})
if 'optimization' not in user_settings:
user_settings['optimization'] = {}
# Aktualisiere die Optimierungseinstellungen
user_settings['optimization'].update(settings)
session['user_settings'] = user_settings
# Einstellungen in der Datenbank speichern, wenn möglich
if hasattr(current_user, 'settings'):
import json
current_user.settings = json.dumps(user_settings)
current_user.updated_at = datetime.now()
db_session.commit()
app_logger.info(f"Optimierungs-Einstellungen für Benutzer {current_user.id} aktualisiert")
return jsonify({
'success': True,
'message': 'Optimierungs-Einstellungen erfolgreich gespeichert'
})
except Exception as e:
db_session.rollback()
app_logger.error(f"Fehler beim Speichern der Optimierungs-Einstellungen: {str(e)}")
return jsonify({
'success': False,
'error': f'Fehler beim Speichern der Einstellungen: {str(e)}'
}), 500
finally:
db_session.close()
# ===== OPTIMIERUNGS-ALGORITHMUS-FUNKTIONEN =====
def apply_round_robin_optimization(jobs, printers, db_session):
"""
Round-Robin-Optimierung: Gleichmäßige Verteilung der Jobs auf Drucker
Verteilt Jobs nacheinander auf verfügbare Drucker für optimale Balance
"""
optimized_count = 0
printer_index = 0
for job in jobs:
if printer_index >= len(printers):
printer_index = 0
# Job dem nächsten Drucker zuweisen
job.printer_id = printers[printer_index].id
job.assigned_at = datetime.now()
optimized_count += 1
printer_index += 1
return optimized_count
def apply_load_balance_optimization(jobs, printers, db_session):
"""
Load-Balancing-Optimierung: Jobs basierend auf aktueller Auslastung verteilen
Berücksichtigt die aktuelle Drucker-Auslastung für optimale Verteilung
"""
optimized_count = 0
# Aktuelle Drucker-Auslastung berechnen
printer_loads = {}
for printer in printers:
current_jobs = db_session.query(Job).filter(
Job.printer_id == printer.id,
Job.status.in_(['running', 'queued'])
).count()
printer_loads[printer.id] = current_jobs
for job in jobs:
# Drucker mit geringster Auslastung finden
min_load_printer_id = min(printer_loads, key=printer_loads.get)
job.printer_id = min_load_printer_id
job.assigned_at = datetime.now()
# Auslastung für nächste Iteration aktualisieren
printer_loads[min_load_printer_id] += 1
optimized_count += 1
return optimized_count
def apply_priority_optimization(jobs, printers, db_session):
"""
Prioritätsbasierte Optimierung: Jobs nach Priorität und verfügbaren Druckern verteilen
Hochpriorisierte Jobs erhalten bevorzugte Druckerzuweisung
"""
optimized_count = 0
# Jobs nach Priorität sortieren
priority_order = {'urgent': 1, 'high': 2, 'normal': 3, 'low': 4}
sorted_jobs = sorted(jobs, key=lambda j: priority_order.get(getattr(j, 'priority', 'normal'), 3))
# Hochpriorisierte Jobs den besten verfügbaren Druckern zuweisen
printer_assignments = {printer.id: 0 for printer in printers}
for job in sorted_jobs:
# Drucker mit geringster Anzahl zugewiesener Jobs finden
best_printer_id = min(printer_assignments, key=printer_assignments.get)
job.printer_id = best_printer_id
job.assigned_at = datetime.now()
printer_assignments[best_printer_id] += 1
optimized_count += 1
return optimized_count
def validate_optimization_settings(settings):
"""
Validiert die Optimierungs-Einstellungen auf Korrektheit und Sicherheit
Verhindert ungültige Parameter die das System beeinträchtigen könnten
"""
try:
# Algorithmus validieren
valid_algorithms = ['round_robin', 'load_balance', 'priority_based']
if settings.get('algorithm') not in valid_algorithms:
return False
# Numerische Werte validieren
max_batch_size = settings.get('max_batch_size', 10)
if not isinstance(max_batch_size, int) or max_batch_size < 1 or max_batch_size > 50:
return False
time_window = settings.get('time_window', 24)
if not isinstance(time_window, int) or time_window < 1 or time_window > 168:
return False
return True
except Exception:
return False
# ===== GASTANTRÄGE API-ROUTEN =====