Доступ к данным в backend строится на Repository Pattern и Unit of Work при строгом разделении доменной модели и ORM.
Repository Pattern
Протокол (core)
В core/<aggregate>/repositories.py объявляется интерфейс:
1 2 3 4 5 | |
Методы принимают и возвращают domain-сущности (Pydantic или dataclass), а не ORM-модели.
Реализация (infra)
В infra/repositories/user_repository.py — реализация на SQLAlchemy:
- маппинг Entity ↔ ORM при чтении/записи;
- использование async session из UoW;
- сложные запросы (фильтры, пагинация) инкапсулируются в методах.
Правила
- Один репозиторий на агрегат (или на ограниченный набор связанных сущностей).
- Репозиторий не возвращает ORM наружу — только domain-модели.
- Транзакции не открываются внутри репозитория — только в Unit of Work.
Unit of Work
Координирует одну бизнес-транзакцию: все репозитории используют общую сессию, коммит/rollback выполняется один раз при выходе из контекста.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Use case получает UoW через DI и выполняет все операции внутри async with uow.transaction().
Миграции (Alembic)
- Миграции хранятся в каждом сервисе в
alembic/versions/. - Генерируются командой
alembic revision --autogenerate -m "description". - Применение:
alembic upgrade head(локально и в CI/CD).
Партиционирование таблицы outbox_events по времени настраивается отдельно (например, через postgres-partition-manager или миграции).
Пул соединений
- Настройка пула в зависимости от окружения (размер пула, таймауты).
- Один пул на приложение; при необходимости разделение для read-replicas.
Связанные страницы
- Service Patterns — место Repository и UoW в архитектуре
- Backend Overview — обзор стека
- Identity service — пример репозиториев и UoW