Files
ALwrity/backend/api/content_planning/utils/error_handlers.py
2025-08-06 12:48:02 +05:30

152 lines
5.6 KiB
Python

"""
Centralized Error Handlers for Content Planning Module
Standardized error handling patterns extracted from the main content planning file.
"""
from typing import Dict, Any, Optional
from fastapi import HTTPException, status
from loguru import logger
import traceback
class ContentPlanningErrorHandler:
"""Centralized error handling for content planning operations."""
@staticmethod
def handle_database_error(error: Exception, operation: str) -> HTTPException:
"""Handle database-related errors."""
logger.error(f"Database error during {operation}: {str(error)}")
logger.error(f"Traceback: {traceback.format_exc()}")
return HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Database operation failed during {operation}: {str(error)}"
)
@staticmethod
def handle_validation_error(error: Exception, field: str) -> HTTPException:
"""Handle validation errors."""
logger.error(f"Validation error for field '{field}': {str(error)}")
return HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=f"Validation error for {field}: {str(error)}"
)
@staticmethod
def handle_not_found_error(resource_type: str, resource_id: Any) -> HTTPException:
"""Handle resource not found errors."""
logger.warning(f"{resource_type} not found: {resource_id}")
return HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"{resource_type} with id {resource_id} not found"
)
@staticmethod
def handle_ai_service_error(error: Exception, service: str) -> HTTPException:
"""Handle AI service errors."""
logger.error(f"AI service error in {service}: {str(error)}")
return HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"AI service {service} is currently unavailable: {str(error)}"
)
@staticmethod
def handle_api_key_error(missing_keys: list) -> HTTPException:
"""Handle API key configuration errors."""
logger.error(f"Missing API keys: {missing_keys}")
return HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"AI services are not properly configured. Missing keys: {', '.join(missing_keys)}"
)
@staticmethod
def handle_general_error(error: Exception, operation: str) -> HTTPException:
"""Handle general errors."""
logger.error(f"General error during {operation}: {str(error)}")
logger.error(f"Exception type: {type(error)}")
logger.error(f"Traceback: {traceback.format_exc()}")
return HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Error during {operation}: {str(error)}"
)
@staticmethod
def create_error_response(
status_code: int,
message: str,
error_type: str = "general",
details: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
"""Create standardized error response."""
error_response = {
"status": "error",
"error_type": error_type,
"message": message,
"status_code": status_code,
"timestamp": "2024-08-01T10:00:00Z" # This should be dynamic
}
if details:
error_response["details"] = details
return error_response
# Common error messages
ERROR_MESSAGES = {
"strategy_not_found": "Content strategy not found",
"calendar_event_not_found": "Calendar event not found",
"gap_analysis_not_found": "Content gap analysis not found",
"user_not_found": "User not found",
"invalid_request": "Invalid request data",
"database_connection": "Database connection failed",
"ai_service_unavailable": "AI service is currently unavailable",
"validation_failed": "Request validation failed",
"permission_denied": "Permission denied",
"rate_limit_exceeded": "Rate limit exceeded",
"internal_server_error": "Internal server error",
"service_unavailable": "Service temporarily unavailable"
}
# Error status codes mapping
ERROR_STATUS_CODES = {
"not_found": status.HTTP_404_NOT_FOUND,
"validation_error": status.HTTP_422_UNPROCESSABLE_ENTITY,
"bad_request": status.HTTP_400_BAD_REQUEST,
"unauthorized": status.HTTP_401_UNAUTHORIZED,
"forbidden": status.HTTP_403_FORBIDDEN,
"not_found": status.HTTP_404_NOT_FOUND,
"conflict": status.HTTP_409_CONFLICT,
"internal_error": status.HTTP_500_INTERNAL_SERVER_ERROR,
"service_unavailable": status.HTTP_503_SERVICE_UNAVAILABLE
}
def log_error(error: Exception, context: str, user_id: Optional[int] = None):
"""Log error with context information."""
logger.error(f"Error in {context}: {str(error)}")
if user_id:
logger.error(f"User ID: {user_id}")
logger.error(f"Exception type: {type(error)}")
logger.error(f"Traceback: {traceback.format_exc()}")
def create_http_exception(
error_type: str,
message: str,
status_code: Optional[int] = None,
details: Optional[Dict[str, Any]] = None
) -> HTTPException:
"""Create HTTP exception with standardized error handling."""
if status_code is None:
status_code = ERROR_STATUS_CODES.get(error_type, status.HTTP_500_INTERNAL_SERVER_ERROR)
logger.error(f"HTTP Exception: {error_type} - {message}")
if details:
logger.error(f"Error details: {details}")
return HTTPException(
status_code=status_code,
detail=message
)