bugfix
This commit is contained in:
@@ -200,6 +200,9 @@ ALLOWED_TARGET_BRANCHES = []
|
|||||||
# GLOBALE HELPER FUNCTIONS (PART 1: Retry Decorator)
|
# GLOBALE HELPER FUNCTIONS (PART 1: Retry Decorator)
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
# Imports für den Retry Decorator (um NameErrors zu vermeiden)
|
||||||
|
from openai.error import AuthenticationError, OpenAIError, RateLimitError, APIError, Timeout, InvalidRequestError, ServiceUnavailableError # Beispielhafte spezifische Fehler
|
||||||
|
|
||||||
# Logger fuer den Retry Decorator selbst (Nutzt den globalen Root Logger)
|
# Logger fuer den Retry Decorator selbst (Nutzt den globalen Root Logger)
|
||||||
decorator_logger = logging.getLogger(__name__ + ".Retry")
|
decorator_logger = logging.getLogger(__name__ + ".Retry")
|
||||||
|
|
||||||
@@ -229,7 +232,7 @@ def retry_on_failure(func):
|
|||||||
# Fehler loggen und weitergeben, wenn keine Retries konfiguriert sind
|
# Fehler loggen und weitergeben, wenn keine Retries konfiguriert sind
|
||||||
decorator_logger.error(f"FEHLER bei '{effective_func_name}' (keine Retries konfiguriert). {type(e).__name__} - {str(e)[:150]}...")
|
decorator_logger.error(f"FEHLER bei '{effective_func_name}' (keine Retries konfiguriert). {type(e).__name__} - {str(e)[:150]}...")
|
||||||
# Log traceback fuer unerwartete Fehler (nicht die spezifischen API/Netzwerkfehler)
|
# Log traceback fuer unerwartete Fehler (nicht die spezifischen API/Netzwerkfehler)
|
||||||
if not isinstance(e, (requests.exceptions.RequestException, gspread.exceptions.APIError, openai.error.OpenAIError, wikipedia.exceptions.WikipediaException)):
|
if not isinstance(e, (requests.exceptions.RequestException, gspread.exceptions.APIError, OpenAIError, wikipedia.exceptions.WikipediaException)): # <<< GEÄNDERT (openai.error.OpenAIError -> OpenAIError)
|
||||||
decorator_logger.exception("Details zum Fehler:")
|
decorator_logger.exception("Details zum Fehler:")
|
||||||
raise e # Re-raise the exception
|
raise e # Re-raise the exception
|
||||||
|
|
||||||
@@ -245,7 +248,7 @@ def retry_on_failure(func):
|
|||||||
return func(*args, **kwargs) # Call the original function
|
return func(*args, **kwargs) # Call the original function
|
||||||
|
|
||||||
# Spezifische Exceptions, die ein Retry nicht rechtfertigen (permanente Fehler)
|
# Spezifische Exceptions, die ein Retry nicht rechtfertigen (permanente Fehler)
|
||||||
except (gspread.exceptions.SpreadsheetNotFound, openai.error.AuthenticationError, ValueError) as e:
|
except (gspread.exceptions.SpreadsheetNotFound, AuthenticationError, ValueError) as e: # <<< GEÄNDERT (openai.error.AuthenticationError -> AuthenticationError)
|
||||||
# Diese Fehler deuten auf ein permanentes Problem hin (falsche URL, falscher Key, falsche Eingabe)
|
# Diese Fehler deuten auf ein permanentes Problem hin (falsche URL, falscher Key, falsche Eingabe)
|
||||||
decorator_logger.critical(f"❌ ENDGUELTIGER FEHLER bei '{effective_func_name}': Permanentes Problem erkannt. {type(e).__name__} - {str(e)[:150]}...")
|
decorator_logger.critical(f"❌ ENDGUELTIGER FEHLER bei '{effective_func_name}': Permanentes Problem erkannt. {type(e).__name__} - {str(e)[:150]}...")
|
||||||
decorator_logger.exception("Details:") # Log traceback fuer permanente Fehler
|
decorator_logger.exception("Details:") # Log traceback fuer permanente Fehler
|
||||||
@@ -269,20 +272,24 @@ def retry_on_failure(func):
|
|||||||
|
|
||||||
|
|
||||||
# Fangen Sie andere wiederholbare Exceptions (Netzwerk, Rate Limit, Timeout etc.)
|
# Fangen Sie andere wiederholbare Exceptions (Netzwerk, Rate Limit, Timeout etc.)
|
||||||
except (requests.exceptions.RequestException, gspread.exceptions.APIError, openai.error.OpenAIError, wikipedia.exceptions.WikipediaException) as e:
|
except (requests.exceptions.RequestException, gspread.exceptions.APIError, OpenAIError, wikipedia.exceptions.WikipediaException) as e: # <<< GEÄNDERT (openai.error.OpenAIError -> OpenAIError)
|
||||||
error_msg = str(e)
|
error_msg = str(e)
|
||||||
error_type = type(e).__name__
|
error_type = type(e).__name__
|
||||||
|
|
||||||
if attempt < max_retries_config - 1: # Wenn nicht der letzte Versuch
|
if attempt < max_retries_config - 1: # Wenn nicht der letzte Versuch
|
||||||
wait_time = base_delay * (2 ** attempt) + random.uniform(0, 1) # Exponentieller Backoff mit Jitter
|
wait_time = base_delay * (2 ** attempt) + random.uniform(0, 1) # Exponentieller Backoff mit Jitter
|
||||||
# Loggen Sie den spezifischen Fehler und die Wartezeit
|
# Loggen Sie den spezifischen Fehler und die Wartezeit
|
||||||
if isinstance(e, gspread.exceptions.APIError) and hasattr(e, 'response') and e.response is not None and e.response.status_code == 429:
|
if isinstance(e, RateLimitError): # <<< GEÄNDERT (Prüfung auf spezifischen OpenAI Fehler)
|
||||||
decorator_logger.warning(f"🚦 RATE LIMIT ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
decorator_logger.warning(f"🚦 RATE LIMIT ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
||||||
|
elif isinstance(e, Timeout) and isinstance(e, OpenAIError): # <<< GEÄNDERT (Prüfung auf OpenAI Timeout)
|
||||||
|
decorator_logger.warning(f"⏰ OPENAI TIMEOUT ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
||||||
|
elif isinstance(e, gspread.exceptions.APIError) and hasattr(e, 'response') and e.response is not None and e.response.status_code == 429: # <<< GEÄNDERT (Gspread Rate Limit Check)
|
||||||
|
decorator_logger.warning(f"🚦 GSPREAD RATE LIMIT ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
||||||
elif isinstance(e, requests.exceptions.Timeout):
|
elif isinstance(e, requests.exceptions.Timeout):
|
||||||
decorator_logger.warning(f"⏰ TIMEOUT ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
decorator_logger.warning(f"⏰ REQUESTS TIMEOUT ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
||||||
elif isinstance(e, requests.exceptions.RequestException): # Allgemeine RequestException
|
elif isinstance(e, requests.exceptions.RequestException): # Allgemeine RequestException
|
||||||
decorator_logger.warning(f"🌐 NETZWERKFEHLER ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
decorator_logger.warning(f"🌐 NETZWERKFEHLER ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
||||||
elif isinstance(e, openai.error.OpenAIError): # Allgemeine OpenAI Fehler
|
elif isinstance(e, OpenAIError): # Allgemeine OpenAI Fehler
|
||||||
decorator_logger.warning(f"🤖 OPENAI FEHLER ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
decorator_logger.warning(f"🤖 OPENAI FEHLER ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
||||||
elif isinstance(e, wikipedia.exceptions.WikipediaException): # Allgemeine Wikipedia Fehler
|
elif isinstance(e, wikipedia.exceptions.WikipediaException): # Allgemeine Wikipedia Fehler
|
||||||
decorator_logger.warning(f"📚 WIKIPEDIA FEHLER ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
decorator_logger.warning(f"📚 WIKIPEDIA FEHLER ({error_type}) bei '{effective_func_name}' (Versuch {attempt+1}/{max_retries_config}). {error_msg[:150]}... Warte {wait_time:.2f}s...")
|
||||||
@@ -305,10 +312,8 @@ def retry_on_failure(func):
|
|||||||
# und eine Exception immer zu einer raise e Anweisung führt.
|
# und eine Exception immer zu einer raise e Anweisung führt.
|
||||||
raise RuntimeError(f"Retry decorator logic error: Loop completed unexpectedly for {effective_func_name}. This should not happen.")
|
raise RuntimeError(f"Retry decorator logic error: Loop completed unexpectedly for {effective_func_name}. This should not happen.")
|
||||||
|
|
||||||
|
|
||||||
return wrapper # Gibt die Wrapper-Funktion zurück
|
return wrapper # Gibt die Wrapper-Funktion zurück
|
||||||
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# Ende Retry Decorator Block
|
# Ende Retry Decorator Block
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user