264 lines
8.4 KiB
Markdown
264 lines
8.4 KiB
Markdown
# 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. |