🎉 Verbesserte Backend-Funktionalität durch Windows-sichere Disk-Usage-Bestimmung, Uptime-Berechnung und Einführung eines Kiosk-Timers. Dokumentation aktualisiert und nicht mehr benötigte Dateien entfernt. 🧹
This commit is contained in:
@@ -1 +1,264 @@
|
||||
|
||||
# Shutdown- und Cleanup-Verbesserungen
|
||||
|
||||
## Übersicht
|
||||
|
||||
Die Anwendung hatte Probleme beim ordnungsgemäßen Herunterfahren und Cleanup, die zu hängenden Prozessen und inkonsistenten Zuständen führten. Diese Dokumentation beschreibt die implementierten Verbesserungen.
|
||||
|
||||
## Identifizierte Probleme
|
||||
|
||||
### Vorherige Probleme
|
||||
1. **Mehrfache Signal-Handler**: Verschiedene Module registrierten eigene Signal-Handler, die sich gegenseitig interferiert haben
|
||||
2. **Fehlende Koordination**: Queue Manager, Scheduler und Datenbank-Cleanup wurden unkoordiniert beendet
|
||||
3. **Keine Timeouts**: Cleanup-Operationen konnten unbegrenzt lange dauern
|
||||
4. **Scheduler-Shutdown-Probleme**: Der Scheduler wurde nicht robust genug gestoppt
|
||||
5. **Komplexe Datenbank-Operationen**: Riskante WAL-Mode-Switches während des Shutdowns
|
||||
|
||||
### Symptome in den Logs
|
||||
```
|
||||
🛑 Signal 2 empfangen - fahre System herunter...
|
||||
⚠️ Thread konnte nicht ordnungsgemäß beendet werden
|
||||
❌ Fehler beim Stoppen des Schedulers
|
||||
🔄 Führe robustes Datenbank-Cleanup durch...
|
||||
```
|
||||
|
||||
## Implementierte Lösung: Zentraler Shutdown-Manager
|
||||
|
||||
### Neue Architektur
|
||||
|
||||
#### 1. Zentraler Shutdown-Manager (`utils/shutdown_manager.py`)
|
||||
```python
|
||||
class ShutdownManager:
|
||||
"""
|
||||
Koordiniert alle Cleanup-Operationen mit Timeouts und Prioritäten
|
||||
"""
|
||||
```
|
||||
|
||||
**Hauptfunktionen:**
|
||||
- **Koordinierte Beendigung**: Alle Komponenten werden in der richtigen Reihenfolge gestoppt
|
||||
- **Prioritäts-basiertes Cleanup**: Cleanup-Funktionen werden nach Priorität (1=hoch, 3=niedrig) ausgeführt
|
||||
- **Timeout-Management**: Jede Operation hat ein konfigurierbares Timeout
|
||||
- **Fehlerbehandlung**: Einzelne Fehler stoppen nicht den gesamten Shutdown-Prozess
|
||||
- **Plattform-spezifisch**: Unterstützt Windows und Unix/Linux Signal-Handling
|
||||
|
||||
#### 2. Komponenten-Registrierung
|
||||
```python
|
||||
# Queue Manager registrieren
|
||||
shutdown_manager.register_queue_manager(queue_module)
|
||||
|
||||
# Scheduler registrieren
|
||||
shutdown_manager.register_scheduler(scheduler, SCHEDULER_ENABLED)
|
||||
|
||||
# Datenbank-Cleanup registrieren
|
||||
shutdown_manager.register_database_cleanup()
|
||||
|
||||
# Windows Thread Manager registrieren
|
||||
shutdown_manager.register_windows_thread_manager()
|
||||
```
|
||||
|
||||
#### 3. Prioritäten-System
|
||||
- **Priorität 1 (Hoch)**: Queue Manager, Scheduler - werden zuerst gestoppt
|
||||
- **Priorität 2 (Mittel)**: Windows Thread Manager - wird in der Mitte gestoppt
|
||||
- **Priorität 3 (Niedrig)**: Datenbank-Cleanup - wird am Ende ausgeführt
|
||||
|
||||
### Verbesserungen im Detail
|
||||
|
||||
#### Queue Manager (`utils/queue_manager.py`)
|
||||
**Vorher:**
|
||||
- Registrierte eigene Signal-Handler, die interferierten
|
||||
- Feste 10-Sekunden-Timeouts ohne Flexibilität
|
||||
- Thread-Join ohne Fallback-Strategien
|
||||
|
||||
**Nachher:**
|
||||
```python
|
||||
def __init__(self, register_signal_handlers: bool = True):
|
||||
# Signal-Handler nur wenn explizit gewünscht
|
||||
if register_signal_handlers and os.name == 'nt':
|
||||
self._register_signal_handlers()
|
||||
```
|
||||
|
||||
**Verbesserungen:**
|
||||
- Optionale Signal-Handler-Registrierung
|
||||
- Prüfung auf zentralen Shutdown-Manager
|
||||
- Reduzierte Timeouts (5 Sekunden)
|
||||
- Daemon-Thread-Fallback für automatische Beendigung
|
||||
- Verbesserte Fehlerbehandlung
|
||||
|
||||
#### Scheduler-Integration
|
||||
**Vorher:**
|
||||
```python
|
||||
scheduler.stop() # Einfache Stop-Methode
|
||||
```
|
||||
|
||||
**Nachher:**
|
||||
```python
|
||||
def stop_scheduler():
|
||||
if hasattr(scheduler, 'shutdown'):
|
||||
scheduler.shutdown(wait=True) # Robustere Methode
|
||||
elif hasattr(scheduler, 'stop'):
|
||||
scheduler.stop()
|
||||
```
|
||||
|
||||
#### Datenbank-Cleanup
|
||||
**Vorher:**
|
||||
- Riskante WAL-Mode-Switches während Shutdown
|
||||
- Komplexe Operationen ohne Timeout
|
||||
|
||||
**Nachher:**
|
||||
```python
|
||||
def safe_database_cleanup():
|
||||
# Kein riskantes Mode-Switching beim Shutdown
|
||||
result = safe_database_cleanup(force_mode_switch=False)
|
||||
|
||||
# Fallback auf einfaches WAL-Checkpoint
|
||||
result = conn.execute(text("PRAGMA wal_checkpoint(PASSIVE)"))
|
||||
```
|
||||
|
||||
### Konfiguration und Verwendung
|
||||
|
||||
#### Startup-Konfiguration in `app.py`
|
||||
```python
|
||||
# Initialisiere zentralen Shutdown-Manager
|
||||
from utils.shutdown_manager import get_shutdown_manager
|
||||
shutdown_manager = get_shutdown_manager(timeout=45)
|
||||
|
||||
# Registriere alle Komponenten
|
||||
shutdown_manager.register_queue_manager(queue_module)
|
||||
shutdown_manager.register_scheduler(scheduler, SCHEDULER_ENABLED)
|
||||
shutdown_manager.register_database_cleanup()
|
||||
shutdown_manager.register_windows_thread_manager()
|
||||
```
|
||||
|
||||
#### Fallback-Mechanismus
|
||||
Falls der Shutdown-Manager nicht verfügbar ist, wird ein Fallback-Signal-Handler verwendet:
|
||||
```python
|
||||
except ImportError as e:
|
||||
# Fallback auf vereinfachte Signal-Handler
|
||||
def fallback_signal_handler(sig, frame):
|
||||
stop_queue_manager()
|
||||
if scheduler:
|
||||
scheduler.shutdown(wait=True)
|
||||
sys.exit(0)
|
||||
```
|
||||
|
||||
### Timeout-Konfiguration
|
||||
|
||||
| Komponente | Timeout | Begründung |
|
||||
|------------|---------|------------|
|
||||
| Queue Manager | 15s | Zeit für Thread-Beendigung und Cleanup |
|
||||
| Scheduler | 10s | Zeit für laufende Jobs zu beenden |
|
||||
| Datenbank-Cleanup | 20s | Zeit für WAL-Checkpoint und Optimierung |
|
||||
| Windows Thread Manager | 15s | Zeit für alle verwalteten Threads |
|
||||
| **Gesamt** | **45s** | Maximum für komplettes Shutdown |
|
||||
|
||||
### Signal-Handler-Koordination
|
||||
|
||||
#### Vorher (Problematisch)
|
||||
```
|
||||
app.py -> SIGINT, SIGTERM, SIGBREAK
|
||||
queue_manager.py -> SIGINT, SIGTERM
|
||||
windows_fixes.py -> SIGINT, SIGTERM, SIGBREAK
|
||||
```
|
||||
**Problem:** Mehrfache Handler interferieren, inkonsistente Cleanup-Reihenfolge
|
||||
|
||||
#### Nachher (Koordiniert)
|
||||
```
|
||||
shutdown_manager.py -> SIGINT, SIGTERM, SIGBREAK (zentral)
|
||||
queue_manager.py -> Keine Handler (oder optional als Fallback)
|
||||
windows_fixes.py -> Registriert beim Shutdown-Manager
|
||||
```
|
||||
|
||||
### Monitoring und Debugging
|
||||
|
||||
#### Detaillierte Logs
|
||||
```
|
||||
🔧 Shutdown-Manager initialisiert
|
||||
✅ Queue Manager beim Shutdown-Manager registriert
|
||||
🔄 Starte koordiniertes System-Shutdown...
|
||||
🔄 Stoppe 1 registrierte Komponenten...
|
||||
🧹 Führe 4 Cleanup-Funktionen aus...
|
||||
✅ Koordiniertes Shutdown abgeschlossen in 3.2s
|
||||
🏁 System wird beendet...
|
||||
```
|
||||
|
||||
#### Timeout-Überwachung
|
||||
```
|
||||
✅ Queue Manager abgeschlossen in 2.1s
|
||||
⏱️ Datenbank Cleanup Timeout nach 20.0s
|
||||
❌ Fehler bei Cleanup 'Windows Thread Manager': Connection refused
|
||||
```
|
||||
|
||||
### Fehlerbehandlung
|
||||
|
||||
#### Robuste Cleanup-Ausführung
|
||||
- **Einzelfehler stoppen nicht das gesamte Shutdown**
|
||||
- **Timeouts verhindern hängende Operationen**
|
||||
- **Fallback-Strategien für kritische Komponenten**
|
||||
- **Detaillierte Fehler-Logs für Debugging**
|
||||
|
||||
#### Graceful Degradation
|
||||
```python
|
||||
try:
|
||||
# Versuche optimalen Cleanup
|
||||
safe_database_cleanup()
|
||||
except Exception:
|
||||
# Fallback auf minimalen Cleanup
|
||||
basic_wal_checkpoint()
|
||||
```
|
||||
|
||||
## Testen der Verbesserungen
|
||||
|
||||
### Test-Szenarien
|
||||
1. **Normales Shutdown**: `Ctrl+C` oder `SIGTERM`
|
||||
2. **Forciertes Shutdown**: Mehrfache `Ctrl+C`
|
||||
3. **Timeout-Verhalten**: Simuliere hängende Komponenten
|
||||
4. **Komponenten-Ausfälle**: Simuliere Fehler in einzelnen Cleanup-Funktionen
|
||||
|
||||
### Erwartete Verbesserungen
|
||||
- **Reduzierte Shutdown-Zeit**: Von >30s auf <10s in normalen Fällen
|
||||
- **Konsistente Logs**: Klare Shutdown-Sequenz sichtbar
|
||||
- **Keine hängenden Prozesse**: Alle Threads werden ordnungsgemäß beendet
|
||||
- **Robuste Datenbank**: Keine WAL-Korruption oder Lock-Probleme
|
||||
|
||||
## Wartung und Erweiterung
|
||||
|
||||
### Neue Komponenten hinzufügen
|
||||
```python
|
||||
# Für Komponenten mit stop()-Methode
|
||||
shutdown_manager.register_component("Meine Komponente", component, "stop")
|
||||
|
||||
# Für Cleanup-Funktionen
|
||||
shutdown_manager.register_cleanup_function(
|
||||
func=my_cleanup_function,
|
||||
name="Meine Cleanup-Funktion",
|
||||
priority=2,
|
||||
timeout=15
|
||||
)
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### Häufige Probleme
|
||||
1. **Import-Fehler**: Shutdown-Manager nicht gefunden -> Fallback wird verwendet
|
||||
2. **Timeout-Überschreitungen**: Komponente reagiert nicht -> Wird übersprungen
|
||||
3. **Signal-Handler-Konflikte**: Alte Handler noch registriert -> Deregistrierung nötig
|
||||
|
||||
#### Debug-Logs aktivieren
|
||||
```python
|
||||
shutdown_logger.setLevel(logging.DEBUG)
|
||||
```
|
||||
|
||||
### Zukünftige Verbesserungen
|
||||
- **Health-Checks**: Überwachung der Komponenten-Zustände
|
||||
- **Konfigurierbares Verhalten**: Externe Konfiguration für Timeouts und Prioritäten
|
||||
- **Metrics**: Sammlung von Shutdown-Performance-Daten
|
||||
- **Web-Interface**: Admin-Interface für Shutdown-Management
|
||||
|
||||
## Fazit
|
||||
|
||||
Die Shutdown-Verbesserungen lösen die ursprünglichen Probleme durch:
|
||||
- **Zentrale Koordination** aller Cleanup-Operationen
|
||||
- **Timeout-basierte** Fehlerbehandlung
|
||||
- **Prioritäts-gesteuerte** Ausführungsreihenfolge
|
||||
- **Robuste Fallback-Mechanismen**
|
||||
|
||||
Das Ergebnis ist ein zuverlässiges, schnelles und debugbares Shutdown-Verhalten.
|
Reference in New Issue
Block a user