🎉 Improved backend functionality & documentation, optimized database files, and introduced shutdown management 🧹
This commit is contained in:
@@ -81,7 +81,7 @@ class PrinterQueueManager:
|
||||
Verbesserte Version mit ordnungsgemäßem Thread-Management für Windows.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, register_signal_handlers: bool = True):
|
||||
self.is_running = False
|
||||
self.monitor_thread = None
|
||||
self.shutdown_event = threading.Event() # Sauberes Shutdown-Signal
|
||||
@@ -89,65 +89,109 @@ class PrinterQueueManager:
|
||||
self.last_status_cache = {} # Cache für letzten bekannten Status
|
||||
self.notification_cooldown = {} # Verhindert Spam-Benachrichtigungen
|
||||
self._lock = threading.Lock() # Thread-Sicherheit
|
||||
self._signal_handlers_registered = False
|
||||
|
||||
# Windows-spezifische Signal-Handler registrieren
|
||||
if os.name == 'nt':
|
||||
# Signal-Handler nur registrieren wenn explizit gewünscht
|
||||
# (Verhindert Interferenzen mit zentralem Shutdown-Manager)
|
||||
if register_signal_handlers and os.name == 'nt':
|
||||
self._register_signal_handlers()
|
||||
|
||||
def _register_signal_handlers(self):
|
||||
"""Windows-spezifische Signal-Handler registrieren (nur wenn gewünscht)"""
|
||||
if self._signal_handlers_registered:
|
||||
return
|
||||
|
||||
try:
|
||||
# Prüfe ob bereits zentrale Signal-Handler existieren
|
||||
try:
|
||||
from utils.shutdown_manager import is_shutdown_requested
|
||||
if is_shutdown_requested is not None:
|
||||
queue_logger.info("🔄 Zentrale Signal-Handler erkannt - deaktiviere lokale Handler")
|
||||
return
|
||||
except ImportError:
|
||||
pass # Kein zentraler Manager verfügbar, verwende lokale Handler
|
||||
|
||||
signal.signal(signal.SIGINT, self._signal_handler)
|
||||
signal.signal(signal.SIGTERM, self._signal_handler)
|
||||
self._signal_handlers_registered = True
|
||||
queue_logger.debug("✅ Lokale Signal-Handler für Queue Manager registriert")
|
||||
|
||||
except Exception as e:
|
||||
queue_logger.warning(f"⚠️ Lokale Signal-Handler konnten nicht registriert werden: {e}")
|
||||
|
||||
def _signal_handler(self, signum, frame):
|
||||
"""Signal-Handler für ordnungsgemäßes Shutdown."""
|
||||
"""Signal-Handler für ordnungsgemäßes Shutdown (nur als Fallback)."""
|
||||
queue_logger.warning(f"🛑 Signal {signum} empfangen - stoppe Queue Manager...")
|
||||
self.stop()
|
||||
|
||||
def start(self):
|
||||
"""Startet den Queue-Manager mit verbessertem Thread-Management."""
|
||||
with self._lock:
|
||||
if not self.is_running:
|
||||
self.is_running = True
|
||||
self.shutdown_event.clear()
|
||||
self.monitor_thread = threading.Thread(target=self._monitor_loop, daemon=False)
|
||||
self.monitor_thread.name = "PrinterQueueMonitor"
|
||||
|
||||
# Windows Thread-Manager verwenden falls verfügbar
|
||||
if os.name == 'nt' and get_windows_thread_manager:
|
||||
try:
|
||||
thread_manager = get_windows_thread_manager()
|
||||
thread_manager.register_thread(self.monitor_thread)
|
||||
thread_manager.register_cleanup_function(self.stop)
|
||||
queue_logger.debug("✅ Queue Manager bei Windows Thread-Manager registriert")
|
||||
except Exception as e:
|
||||
queue_logger.warning(f"⚠️ Windows Thread-Manager nicht verfügbar: {str(e)}")
|
||||
|
||||
self.monitor_thread.start()
|
||||
queue_logger.info("✅ Printer Queue Manager erfolgreich gestartet")
|
||||
|
||||
def stop(self):
|
||||
"""Stoppt den Queue-Manager ordnungsgemäß."""
|
||||
"""Startet den Queue-Manager mit verbessertem Shutdown-Handling."""
|
||||
with self._lock:
|
||||
if self.is_running:
|
||||
queue_logger.info("🔄 Beende Queue Manager...")
|
||||
self.is_running = False
|
||||
self.shutdown_event.set()
|
||||
queue_logger.warning("Queue-Manager läuft bereits")
|
||||
return self
|
||||
|
||||
queue_logger.info("🚀 Starte Printer Queue Manager...")
|
||||
self.is_running = True
|
||||
self.shutdown_event.clear()
|
||||
|
||||
# Monitor-Thread mit Daemon-Flag für automatische Beendigung
|
||||
self.monitor_thread = threading.Thread(
|
||||
target=self._monitor_loop,
|
||||
name="PrinterQueueMonitor",
|
||||
daemon=True # Automatische Beendigung bei Programm-Ende
|
||||
)
|
||||
self.monitor_thread.start()
|
||||
|
||||
queue_logger.info("✅ Printer Queue Manager gestartet")
|
||||
return self
|
||||
|
||||
def stop(self):
|
||||
"""Stoppt den Queue-Manager ordnungsgemäß mit verbessertem Timeout-Handling."""
|
||||
with self._lock:
|
||||
if not self.is_running:
|
||||
queue_logger.debug("Queue-Manager ist bereits gestoppt")
|
||||
return
|
||||
|
||||
if self.monitor_thread and self.monitor_thread.is_alive():
|
||||
queue_logger.debug("⏳ Warte auf Thread-Beendigung...")
|
||||
self.monitor_thread.join(timeout=10)
|
||||
queue_logger.info("🔄 Beende Queue Manager...")
|
||||
self.is_running = False
|
||||
self.shutdown_event.set()
|
||||
|
||||
if self.monitor_thread and self.monitor_thread.is_alive():
|
||||
queue_logger.debug("⏳ Warte auf Thread-Beendigung...")
|
||||
|
||||
# Verbessertes Timeout-Handling
|
||||
try:
|
||||
self.monitor_thread.join(timeout=5.0) # Reduziertes Timeout
|
||||
|
||||
if self.monitor_thread.is_alive():
|
||||
queue_logger.warning("⚠️ Thread konnte nicht ordnungsgemäß beendet werden")
|
||||
queue_logger.warning("⚠️ Thread konnte nicht in 5s beendet werden - setze als Daemon")
|
||||
# Thread als Daemon markieren für automatische Beendigung
|
||||
self.monitor_thread.daemon = True
|
||||
else:
|
||||
queue_logger.info("✅ Monitor-Thread erfolgreich beendet")
|
||||
|
||||
self.monitor_thread = None
|
||||
queue_logger.info("❌ Printer Queue Manager gestoppt")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
queue_logger.error(f"❌ Fehler beim Thread-Join: {e}")
|
||||
|
||||
self.monitor_thread = None
|
||||
queue_logger.info("❌ Printer Queue Manager gestoppt")
|
||||
|
||||
def _monitor_loop(self):
|
||||
"""Hauptschleife für die Überwachung der Drucker mit verbessertem Shutdown-Handling."""
|
||||
queue_logger.info(f"🔄 Queue-Überwachung gestartet (Intervall: {self.check_interval} Sekunden)")
|
||||
|
||||
while self.is_running and not self.shutdown_event.is_set():
|
||||
try:
|
||||
# Prüfe auf zentrales Shutdown-Signal
|
||||
try:
|
||||
from utils.shutdown_manager import is_shutdown_requested
|
||||
if is_shutdown_requested():
|
||||
queue_logger.info("🛑 Zentrales Shutdown-Signal empfangen - beende Monitor-Loop")
|
||||
break
|
||||
except ImportError:
|
||||
pass # Kein zentraler Manager verfügbar
|
||||
|
||||
self._check_waiting_jobs()
|
||||
|
||||
# Verwende Event.wait() statt time.sleep() für unterbrechbares Warten
|
||||
@@ -379,10 +423,37 @@ def get_queue_manager() -> PrinterQueueManager:
|
||||
return _queue_manager_instance
|
||||
|
||||
def start_queue_manager():
|
||||
"""Startet den globalen Queue-Manager."""
|
||||
manager = get_queue_manager()
|
||||
manager.start()
|
||||
return manager
|
||||
"""Startet den globalen Queue-Manager sicher und ohne Signal-Handler-Interferenzen."""
|
||||
global _queue_manager_instance
|
||||
with _queue_manager_lock:
|
||||
if _queue_manager_instance is not None:
|
||||
queue_logger.warning("Queue-Manager läuft bereits")
|
||||
return _queue_manager_instance
|
||||
|
||||
try:
|
||||
queue_logger.info("🚀 Initialisiere neuen Queue-Manager...")
|
||||
|
||||
# Prüfe ob zentraler Shutdown-Manager verfügbar ist
|
||||
register_signals = True
|
||||
try:
|
||||
from utils.shutdown_manager import is_shutdown_requested
|
||||
if is_shutdown_requested is not None:
|
||||
queue_logger.info("🔄 Zentrale Shutdown-Verwaltung erkannt - deaktiviere lokale Signal-Handler")
|
||||
register_signals = False
|
||||
except ImportError:
|
||||
queue_logger.debug("Kein zentraler Shutdown-Manager verfügbar - verwende lokale Signal-Handler")
|
||||
|
||||
# Erstelle Queue-Manager ohne Signal-Handler wenn zentraler Manager vorhanden
|
||||
_queue_manager_instance = PrinterQueueManager(register_signal_handlers=register_signals)
|
||||
_queue_manager_instance.start()
|
||||
|
||||
queue_logger.info("✅ Queue-Manager erfolgreich gestartet")
|
||||
return _queue_manager_instance
|
||||
|
||||
except Exception as e:
|
||||
queue_logger.error(f"❌ Fehler beim Starten des Queue-Managers: {str(e)}")
|
||||
_queue_manager_instance = None
|
||||
raise
|
||||
|
||||
def stop_queue_manager():
|
||||
"""Stoppt den globalen Queue-Manager definitiv und sicher."""
|
||||
|
Reference in New Issue
Block a user