Структура проекта
umnaya_galereya/
│
├── app/ # Основной код приложения
│ ├── api/ # HTTP слой (FastAPI)
│ │ ├── v1/ # Версия API v1
│ │ │ ├── auth.py # POST /api/v1/photo/auth
│ │ │ ├── photos.py # CRUD для фото
│ │ │ ├── groups.py # Группы дубликатов
│ │ │ ├── metrics.py # GET /metrics (Prometheus)
│ │ │ ├── healthz.py # GET /healthz
│ │ │ └── readyz.py # GET /readyz
│ │ └── depends.py # FastAPI dependencies (get_current_user)
│ │
│ ├── core/ # Ядро: настройки, ошибки, метрики
│ │ ├── config.py # Pydantic Settings (.env)
│ │ ├── errors.py # AppException, ErrorCodes, ErrorResponse
│ │ ├── jwt_utils.py # JWT encode/decode (HMAC-SHA256)
│ │ ├── log.py # Настройка логирования
│ │ ├── metrics.py # Prometheus counter/histogram
│ │ └── context.py # ContextVar для request_id
│ │
│ ├── database/ # Слой доступа к БД
│ │ ├── models.py # SQLAlchemy модели: Token, Group, Photos, PhotoAnalysis
│ │ └── database.py # async engine + session factory
│ │
│ ├── integrations/ # Интеграции с внешними системами
│ │ ├── postgreesql.py # PhotoDatabase, GroupDatabase, TokenDatabase
│ │ ├── minio.py # MinIOStorage (S3)
│ │ ├── kafka.py # KafkaProducer
│ │ └── metrics_db.py # Prometheus метрики из БД
│ │
│ ├── schemas/ # Pydantic модели (request/response)
│ │ ├── auth.py # VKAuthRequest, VKAuthResponse
│ │ ├── photos.py # Upload/Get/List photo схемы
│ │ └── groups.py # DuplicateGroup схемы
│ │
│ ├── services/ # Бизнес-логика
│ │ ├── auth_service.py # VKAuthService (верификация подписи)
│ │ ├── photos_service.py # PhotoService (загрузка, список, детали)
│ │ └── groups_service.py # GroupService (список, детали групп)
│ │
│ ├── worker/ # Фоновый обработчик
│ │ ├── __main__.py # Точка входа: python -m app.worker
│ │ ├── consumer.py # Kafka consumer
│ │ ├── processor.py # Логика обработки фото
│ │ ├── database.py # Операции с БД для worker
│ │ ├── minio_client.py # MinIO клиент для worker
│ │ ├── grpc_client.py # gRPC клиент анализатора
│ │ ├── hasher.py # SHA256 + перцептивный хеш
│ │ └── preview.py # Генерация preview (Pillow)
│ │
│ └── main.py # FastAPI приложение (lifespan, middleware, routes)
│
├── k8s/ # Kubernetes манифесты (11 файлов)
│ ├── 00-namespace.yaml # Namespace: umnaya
│ ├── 01-configmap.yaml # ConfigMap
│ ├── 02-secret.yaml # Secret
│ ├── 03-postgres.yaml # PostgreSQL
│ ├── 04-minio.yaml # MinIO
│ ├── 05-kafka.yaml # Kafka
│ ├── 06-api-deployment.yaml # API + init контейнеры
│ ├── 07-api-service.yaml # API Service
│ ├── 08-worker-deployment.yaml # Worker
│ ├── 09-nginx.yaml # Nginx proxy (для MinIO)
│ └── 10-volumes.yaml # PV + PVC (postgres, minio, kafka)
│
├── migrations/ # Alembic миграции
│ ├── env.py # Конфигурация окружения
│ ├── script.py.mako # Шаблон для новых миграций
│ └── versions/ # Файлы миграций
│ ├── 97952d5ba82e.py # Initial schema (tokens, groups, photos, photo_analysis)
│ ├── 472ec77dc88b.py # Добавлены dominant_color, tags, model_version
│ └── e571cca9d7ca.py # model_version расширена до 100 символов
│
├── AI_artefacts/ # Вспомогательные артефакты AI-сессий
├── grafana_data/ # Данные Grafana (volume)
│
├── .env # Локальный конфиг (не в git)
├── .env.example # Пример конфига
├── .dockerignore
├── .gitignore
│
├── requirements.txt # Зависимости Python
├── Dockerfile # Сборка образа
├── docker-compose.yml # Локальный запуск всех сервисов
├── alembic.ini # Конфиг Alembic
├── analyzer.proto # gRPC proto контракт
├── prometheus.yml # Конфиг Prometheus
└── startup_guide.md # Инструкция по запуску (устаревшая)
Описание модулей
app.core — Ядро
Модуль общей инфраструктуры. Не зависит от бизнес-логики.
- config.py: загружает переменные окружения через
pydantic-settings, предоставляет объектsettings - errors.py: иерархия исключений (
AppException→PhotoNotFoundError,InvalidFile,AccessDeniedErrorи т.д.), единый формат ответаErrorResponse - jwt_utils.py: HMAC-SHA256 JWT encode/decode без внешних библиотек
- log.py: настройка логгера с поддержкой
request_idчерезContextVar - metrics.py: декларация Prometheus метрик (Counter, Histogram)
- context.py:
ContextVarдля сквозного ID запроса
app.api.v1 — HTTP слой
Обработчики запросов. Только валидация и вызов сервисов.
- Используют
Depends(get_current_user)для опциональной JWT-аутентификации - Каждый роутер подключается в
main.py - Все ответы в Pydantic-схемах из
app.schemas
app.services — Бизнес-логика
- VKAuthService: верифицирует VK подпись (HMAC-SHA256), выдаёт JWT, сохраняет токен в БД
- PhotoService: загрузка (валидация → MinIO → Kafka), список, детали (с анализом и группами)
- GroupService: управление группами дубликатов/идентичных фото
app.integrations — Интеграции
- postgreesql.py: Database классы для каждой сущности (CRUD с SQLAlchemy)
- minio.py: MinIOStorage — загрузка/скачивание/presigned URL с таймаутами и метриками
- kafka.py: KafkaProducer — создание топика, публикация сообщений с retry
- metrics_db.py: агрегация метрик из PostgreSQL в Prometheus-формате
app.worker — Фоновый обработчик
Асинхронный consumer на aiokafka:
- Читает сообщение из Kafka
- Захватывает фото (atomic UPDATE)
- Скачивает оригинал из MinIO
- Вызывает gRPC анализатор (с retry)
- Вычисляет SHA256 и перцептивный хеш
- Генерирует preview через Pillow
- Сохраняет результаты в БД
- Проверяет дубликаты и идентичные фото