Prisma и data layer
Обновлён 14 апр. 2026 г., 17:16 · 0 комментариев
Prisma и data layer
Паспорт документа
- Статус документа: working reference
- Актуально на: 28 марта 2026 года
- Владелец: backend/platform-команда
- Пересмотр: при изменении архитектурных решений, data layer или frontend data patterns
- Область применения: архитектурные и интеграционные справочные документы проекта
- Связанные документы:
Цель документа
Этот документ описывает текущий Prisma-контур Qadam как инженерный источник истины по модели данных, миграциям, генерации клиента и operational-практикам работы с базой.
1. Краткий вывод
В проекте Prisma оформлен не как локальная зависимость apps/api, а как отдельный workspace-пакет @repo/prisma. Это правильная архитектура для монолитного backend-ядра:
- схема данных централизована;
- migrations и generated client лежат рядом;
- seed и селекты живут в одном пакете;
- API и другие backend-слои получают единый источник истины по данным.
Текущий Prisma-контур подходит проекту, но требует дальнейшей инженерной дисциплины:
- schema change должен всегда идти вместе с migration;
- generated client должен обновляться синхронно;
- нужно дожать документацию по данным и аналитике;
- нужно убрать legacy-ощущение, что data layer живёт только “внутри API”.
2. Структура пакета @repo/prisma
Ключевые файлы:
packages/prisma/schema.prismapackages/prisma/migrations/*packages/prisma/generated/prisma/*packages/prisma/seed.tspackages/prisma/selects/*packages/prisma/index.tspackages/prisma/client.tspackages/prisma/enums.ts
Назначение:
schema.prisma— каноническая модель данных;migrations/— история структурных изменений БД;generated/prisma/— сгенерированный Prisma Client;seed.ts— наполнение тестовыми и demo-данными;selects/*— общие безопасные выборки для reuse в backend;index.ts,client.ts,enums.ts— публичные точки экспорта пакета.
3. Генерация и сборка
Generator настроен так:
generator client {
provider = "prisma-client-js"
output = "./generated/prisma"
}
Это означает:
- generated client хранится внутри пакета, а не в
node_modules/.prisma; - backend импортирует клиента через workspace-путь;
- build становится воспроизводимым и прозрачным.
Основные команды:
pnpm --filter @repo/prisma generatepnpm --filter @repo/prisma buildpnpm --filter @repo/prisma migrate:devpnpm --filter @repo/prisma migrate:deploypnpm --filter @repo/prisma seed
4. Runtime-модель Prisma в API
PrismaService в apps/api/src/prisma/prisma.service.ts наследуется от PrismaClient и добавляет production-полезную обвязку:
- primary connection через
DATABASE_URL; - optional read replica через
DATABASE_REPLICA_URL; - метод
$replica()для read-only операций; - lifecycle hooks
onModuleInit/onModuleDestroy; - structured logging через
PinoLogger; - режим
SKIP_EXTERNAL_CONNECTIONS=trueдля export/openapi-задач.
Это важная инженерная деталь: OpenAPI export и похожие offline-задачи не обязаны поднимать реальные DB/Redis connections.
5. Что находится в схеме данных
5.1 Аккаунты и роли
Схема покрывает:
AccountBuyerParentStudentSellerSchoolOnlineSchoolIndividualContributorSellerStaffAdmin
То есть ролевая модель у проекта уже физически зашита на уровне схемы данных.
5.2 Центральная продуктовая сущность
Главная продуктовая сущность — Item.
С ней связаны:
- продавец;
- школа / online school;
- subject и location;
- лиды;
- отзывы;
- media;
- schedules;
- performer groups;
- special offers;
- moderation records.
Именно Item является центром buyer/seller/admin-потоков и основной точкой для дальнейшей аналитики.
5.3 Лиды и отзывы
Схема уже содержит:
LeadReview- их связи с buyer/seller/item
Это важно, потому что аналитика воронки и quality metrics уже может строиться поверх реальных сущностей, а не поверх временных event-only логов.
5.4 Admin и модерация
Для moderation слоя уже есть:
AdminAdminModeration
Это создаёт основу для audit trail и дальнейшей операционной аналитики по модерации.
5.5 Аналитический append-only слой
В схеме есть EventLog.
Это не отдельная BI-схема, а operational analytics log в основном postgres-контуре. Он уже достаточен для:
- product event tracking;
- аудита действий;
- ручных выборок;
- будущего ETL в отдельную аналитическую систему.
6. Миграции
Сейчас в пакете уже есть migrations:
20260312231315_initial_schema20260315211735_add_event_log_table
Это означает, что аналитический слой EventLog уже формально зафиксирован migration-историей, а не только кодом.
Operational-правило для production:
- schema change без migration недопустим;
migrate:deployвыполняется до рестарта сервисов;- факт отсутствия pending migrations должен проверяться в release-пакете.
7. Seed и demo-данные
seed.ts не ограничивается примитивными справочниками. Он создаёт:
- subjects;
- locations;
- продавцов разных типов;
- buyer/demo-данные;
- большой набор айтемов и связанных сущностей.
Практический смысл:
- локальная разработка быстрее стартует;
- buyer/seller/public flows можно быстро прогонять на наполненной БД;
- каталог и reference data не выглядят пустыми на dev/staging.
При этом seed не должен восприниматься как production migration-инструмент. Его задача — development/demo bootstrap.
8. Канонические правила работы с Prisma
- Источник истины по структуре БД — только
packages/prisma/schema.prisma. - Любое изменение схемы должно сопровождаться migration.
- После schema change обязательно прогоняются
generateиbuild. - Backend использует Prisma через
PrismaService, а не создаёт новыеPrismaClientв произвольных местах. - Frontend не должен тянуть Prisma runtime-код.
- Общие enums и select helpers должны жить в
@repo/prisma, а не дублироваться по проекту.
8.1 Правило идентификаторов для аналитического контура
Для аналитического слоя фиксируется отдельное обязательное правило, которое не меняет продуктовую Prisma-схему:
- в backend и operational PostgreSQL источником истины остаются внешние идентификаторы в текущем продуктово-сервисном формате;
- raw/staging слой аналитики принимает эти значения как есть и хранит их как внешние технические ключи
*_id_ext; - внутри аналитической БД любая сущность, которая попадает во внутренние join, факты и витрины, получает собственный surrogate key типа
bigint(*_id); - соответствие
*_id_ext <-> *_idподдерживается через отдельный mapping-слой1:1; - все внутренние join, агрегаты и витрины в аналитике строятся только по внутренним
bigint, а*_id_extостаётся ключом для загрузки, трассировки и сверки с продуктовым контуром.
Это означает, что backend не подстраивает продуктовую схему под аналитические bigint, а аналитический контур не использует внешние UUID/string идентификаторы как основной join key в своих heavy queries.
9. Текущие пробелы и риски
- В
package.json#prismaиспользуется deprecated-конфигурация seed; позже нужен переход наprisma.config.ts. - Нет отдельного документа по retention/архивации для
EventLog. - Нет dedicated read-model / analytics mart поверх operational postgres.
- Нет formal data contract docs по ключевым таблицам уровня BI/аналитики.
- Нет автоматической проверки архитектурного правила “не создавать сырые PrismaClient вне
PrismaService”.
10. Рекомендуемые следующие шаги
- Зафиксировать канонический data contract для
Item,Lead,Review,EventLog. - Документировать allowed read-path через
$replica()и policy использования replica. - Перевести Prisma seed/config на актуальный формат перед Prisma 7.
- Добавить отдельные интеграционные проверки на migrations и critical selects.
- Дальше строить аналитику поверх уже существующего Prisma/EventLog контура, а не вводить параллельный data stack без необходимости.