# Обработка ошибок ## Матрица ошибок по слоям | Слой | Что делаем | Пример | |------|-----------|--------| | **API** | HTTPException с detail и status_code | `raise HTTPException(404, detail="Not found")` | | **Services** | Бизнес-исключения без HTTP-статусов | `raise IdeaNotFoundError(idea_id)` | | **Integrations** | try/except с fallback | `return AIResult(success=False, error=...)` | | **Data/DB** | Ошибки не всплывают выше | Ловим в сервисе | --- ## Иерархия исключений ```python # app/core/exceptions.py class AppError(Exception): """Базовое исключение приложения.""" def __init__(self, message: str, details: dict | None = None): self.message = message self.details = details or {} class NotFoundError(AppError): """Ресурс не найден.""" def __init__(self, resource: str, resource_id: str): super().__init__(f"{resource} not found: {resource_id}", {"resource": resource, "id": resource_id}) class ValidationError(AppError): """Ошибка валидации.""" def __init__(self, field: str, message: str): super().__init__(message, {"field": field}) class AuthError(AppError): """Ошибка аутентификации.""" def __init__(self, message: str = "Authentication failed"): super().__init__(message) class ForbiddenError(AppError): """Нет прав.""" def __init__(self, message: str = "Access denied"): super().__init__(message) ``` --- ## Fallback Pattern (для внешних вызовов) ```python # Паттерн для всех вызовов внешних API async def call_with_fallback(provider: AIProvider, prompt: str) -> AIResult: max_retries = 2 last_error = None for attempt in range(max_retries + 1): try: result = await asyncio.wait_for( provider.analyze(prompt), timeout=10.0 ) if result.success: return result last_error = result except asyncio.TimeoutError: last_error = AIResult(success=False, error="Timeout") except Exception as e: last_error = AIResult(success=False, error=str(e)) if attempt < max_retries: await asyncio.sleep(2 if attempt == 0 else 5) return last_error ``` --- ## Логирование ошибок | Уровень | Когда | Пример | |---------|-------|--------| | DEBUG | Входящие параметры | `Request params: id=123` | | INFO | Успешная операция | `User created: id=456` | | WARNING | Timeout, retry | `Yandex GPT timeout, retry 1/2` | | ERROR | Ошибка внешнего API | `GigaChat 500: Internal error` | | CRITICAL | Исчерпаны все retry | `All AI providers failed for idea 789` | --- ## Graceful Degradation Когда внешний сервис недоступен: 1. **DB недоступна** → 503 Service Unavailable 2. **Redis недоступен** → работаем без кэша (log WARNING) 3. **AI провайдер недоступен** → возвращаем fallback результат 4. **Celery недоступен** → выполняем задачу синхронно --- ## [ASK] Вопросы по обработке ошибок - Нужны ли пользовательские исключения для всех бизнес-сценариев? - Нужен ли sentry или аналогичный мониторинг ошибок? - Как обрабатывать ошибки валидации на фронтенде?