Skip to content

Repository files navigation

Search Docs

Поисковый сервис для текстов документов с интеграцией Elasticsearch и PostgreSQL.

Автор

Юнгблюд Артур

Архитектурные паттерны и подходы

🏗️ Архитектура и разделение слоев

  • API-слой: Реализован через паттерн Router Factory с ленивыми импортами. Эндпоинты выполняют роль тонких контроллеров, отвечая исключительно за маршрутизацию, конфигурацию OpenAPI и HTTP-контракты.
  • Бизнес-логика: Выделена в независимые сценарии использования через паттерн Command.
  • Слой данных: Взаимодействие с базами данных и внешними сервисами полностью изолировано с помощью паттерна Repository.
  • Связанность компонентов: Благодаря строгому соблюдению принципа инверсии зависимостей удалось органично изолировать части приложения друг от друга. Слои получились независимыми, расширяемыми и легко тестируемыми.

⚙️ Управление ресурсами и Concurrency

  • Жизненный цикл: Все основные переиспользуемые сущности и клиенты подключений инициализируются в рамках Lifespan и хранятся непосредственно в состоянии приложения (app.state в FastAPI). Это обеспечивает единую точку конфигурации и эффективное управление системными ресурсами.
  • Асинхронность: Внутри процесса инициализации реализовано конкурентное перестроение индексов с использованием современного механизма asyncio.TaskGroup.
  • Контроль конкурентности: В коде продемонстрировано владение инструментами синхронизации через asyncio.Semaphore, который жестко ограничивает пул одновременных запросов к Elasticsearch для предотвращения сетевого оверхеда.

    💡 Примечание: В текущих масштабах инфраструктуры данное решение является избыточным, однако оно намеренно заложено для демонстрации навыков проектирования высоконагруженных сценариев.

🗄️ Миграции и наполнение данными (Alembic)

  • Сидинг данных: Реализовано динамическое наполнение базы данных из CSV-файла непосредственно в процессе выполнения миграций Alembic (процесс опционален и управляется флагом из конфигурации).
  • Кастомизация миграций: Продемонстрировано умение модифицировать автосгенерированные файлы Alembic и выполнять чистые SQL-запросы.
  • Оптимизация запросов: Данные вставляются пачкой путем передачи списка словарей в метод выполнения. Это полностью исключает проблему N+1 запросов и избыточные сетевые задержки при развертывании приложения.

🧪 Стратегия тестирования

Высокая изолированность архитектурных слоев позволила выстроить эффективную и быструю модель тестирования:

  • Smoke-тесты: Выступают в роли первой линии проверки. Они валидируют успешный запуск базы данных и проверяют доступность приложения через эндпоинт Healthcheck.
  • Функциональные тесты: Проверяют целиком изолированный объект резолвера, подменяя внешний мир и базы данных быстрыми заглушками репозиториев.
  • Интеграционные тесты: Покрывают исключительно слой репозиториев Repository, проверяя корректность запросов в реальной, изолированной тестовой среде (БД и Elasticsearch).
  • E2E-тесты: Запускают приложение целиком в тестовом окружении и проверяют по одному ключевому положительному сценарию на каждый сквозной процесс.

Описание

Сервис предоставляет API для полнотекстового поиска по документам с использованием Elasticsearch в качестве поискового движка. Данные документов хранятся в PostgreSQL, а поисковый индекс — в Elasticsearch.

Основные возможности

  • 🔍 Полнотекстовый поиск по документам с ранжированием по дате создания
  • 📄 Возврат первых 20 документов с полными данными из БД
  • 🗑️ Удаление документов из БД и индекса по ID

Технологический стек

  • Python 3.14
  • FastAPI — веб-фреймворк
  • PostgreSQL — хранение документов
  • Elasticsearch — поисковый индекс
  • SQLAlchemy — ORM
  • Alembic — миграции
  • Docker / Docker Compose — контейнеризация
  • Pytest — тестирование

Требования

  • Docker и Docker Compose
  • Python 3.14 (для локальной разработки)

Быстрый старт

Запуск через Docker Compose

# Клонировать репозиторий
git clone <repository-url>
cd search_docs

# Запустить все сервисы
docker-compose up -d

Сервис будет доступен по адресу: http://localhost:8000

Документация API (OpenAPI): http://localhost:8000/search_docs/docs

Локальная разработка

# Установить uv (если не установлен)
# Создать виртуальное окружение и установить зависимости
uv venv
source .venv/bin/activate
uv pip install -e .

# Запустить PostgreSQL и Elasticsearch через docker-compose
docker-compose up -d db elasticsearch

# Применить миграции
alembic upgrade head

# Загрузить тестовые данные
python -m app.startup

# Запустить сервер
python main.py

Структура проекта

.
├── app/                       # Основной код приложения
│   ├── api/                   # API слои
│   │   ├── health.py          # Healthcheck эндпоинт
│   │   └── v1/                # API v1
│   │       ├── resolvers.py   # Обработчики запросов
│   │       ├── routers.py     # Роутеры
│   │       └── schemas.py     # Pydantic схемы
│   ├── storage/               # Работа с хранилищами
│   │   ├── database.py        # Подключение к БД
│   │   └── elastic.py         # Подключение к Elasticsearch
│   ├── config.py              # Конфигурация приложения
│   ├── logger.py              # Настройка логирования
│   ├── models.py              # SQLAlchemy модели
│   ├── repositories.py        # Репозитории для работы с БД и индексом
│   ├── startapp.py            # lifespan эвенты при старте приложения
│   └── server.py              # Настройка FastAPI приложения
├── alembic/                   # Миграции БД
│   └── versions/              # Файлы миграций
├── tests/                     # Тесты
│   ├── test_01_smoke/         # Смок тесты (Ожидание: долгое поднятие всей инфраструктуры)
│   ├── test_01_functional/    # Функциональные тесты (Ожидание: быстрое, не требуется поднятие инфраструктуры)
│   ├── test_02_integration/   # Интеграционные тесты (Ожидание: долгое поднятие части инфраструктуры, зависит от тестов)
│   └── test_03_e2e/           # End-to-end тесты (Ожидание: долгое поднятие всей инфраструктуры)
├── docker-compose.yaml        # Docker Compose конфигурация
├── Dockerfile                 # Docker образ
├── docs.json                  # OpenAPI документация
├── main.py                    # Точка входа
└── pyproject.toml             # Зависимости проекта

Тестирование

В проекте реализована четырехуровневая стратегия тестирования:

1. Smoke тесты (test_01_smoke)

  • Быстрота выполнения: ⚡ (требуют времени на инициализацию)
  • Цель: Проверка базовой работоспособности и доступности сервисов
  • Особенности: Ожидают долгое поднятие всей инфраструктуры, валидируют старт базы данных и проверяют эндпоинт Healthcheck
  • Запуск: pytest tests/test_01_smoke/

2. Функциональные тесты (test_01_functional)

  • Быстрота выполнения: ⚡⚡⚡ (самые быстрые)
  • Цель: Тестирование бизнес-логики и сервисного слоя
  • Особенности: Используют моки для внешних зависимостей (БД, Elasticsearch)
  • Запуск: pytest tests/test_01_functional/

3. Интеграционные тесты (test_02_integration)

  • Быстрота выполнения: ⚡⚡ (средние)
  • Цель: Проверка взаимодействия с реальными хранилищами
  • Особенности: Поднимают тестовые контейнеры с БД и Elasticsearch
  • Запуск: pytest tests/test_02_integration/

4. End-to-End тесты (test_03_e2e)

  • Быстрота выполнения: ⚡ (самые долгие)
  • Цель: Полная проверка API эндпоинтов в реальной среде
  • Особенности: Тестируют полный цикл: HTTP запрос → обработка → ответ
  • Запуск: pytest tests/test_03_e2e/

Запуск всех тестов

pytest

API Эндпоинты

Поиск документов

POST /search_docs/v1/documents/search?selected_size=20

Тело запроса:

{
  "search_text": "Грибное смузи"
}

Ответ (200):

{
  "documents": [
    {
      "id": 999,
      "text": "Здесь могла бы быть ваша реклама",
      "rubrics": ["VK-191919191"],
      "created_date": "2026-06-30T22:17:14.561073"
    }
  ]
}

Удаление документа

DELETE /search_docs/v1/documents/{id}

Ответ: 204 No Content

Healthcheck

GET /search_docs/health/

Ответ (200):

{
  "status": "ok"
}

Переменные окружения

Создайте файл .env в корне проекта, пример файла .env.example в корне

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages