Qadam Roadmap
проектdocs/architecture/prisma-data-layer.md

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.prisma
  • packages/prisma/migrations/*
  • packages/prisma/generated/prisma/*
  • packages/prisma/seed.ts
  • packages/prisma/selects/*
  • packages/prisma/index.ts
  • packages/prisma/client.ts
  • packages/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 generate
  • pnpm --filter @repo/prisma build
  • pnpm --filter @repo/prisma migrate:dev
  • pnpm --filter @repo/prisma migrate:deploy
  • pnpm --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 Аккаунты и роли

Схема покрывает:

  • Account
  • Buyer
  • Parent
  • Student
  • Seller
  • School
  • OnlineSchool
  • IndividualContributor
  • SellerStaff
  • Admin

То есть ролевая модель у проекта уже физически зашита на уровне схемы данных.

5.2 Центральная продуктовая сущность

Главная продуктовая сущность — Item.

С ней связаны:

  • продавец;
  • школа / online school;
  • subject и location;
  • лиды;
  • отзывы;
  • media;
  • schedules;
  • performer groups;
  • special offers;
  • moderation records.

Именно Item является центром buyer/seller/admin-потоков и основной точкой для дальнейшей аналитики.

5.3 Лиды и отзывы

Схема уже содержит:

  • Lead
  • Review
  • их связи с buyer/seller/item

Это важно, потому что аналитика воронки и quality metrics уже может строиться поверх реальных сущностей, а не поверх временных event-only логов.

5.4 Admin и модерация

Для moderation слоя уже есть:

  • Admin
  • AdminModeration

Это создаёт основу для audit trail и дальнейшей операционной аналитики по модерации.

5.5 Аналитический append-only слой

В схеме есть EventLog.

Это не отдельная BI-схема, а operational analytics log в основном postgres-контуре. Он уже достаточен для:

  • product event tracking;
  • аудита действий;
  • ручных выборок;
  • будущего ETL в отдельную аналитическую систему.

6. Миграции

Сейчас в пакете уже есть migrations:

  • 20260312231315_initial_schema
  • 20260315211735_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

  1. Источник истины по структуре БД — только packages/prisma/schema.prisma.
  2. Любое изменение схемы должно сопровождаться migration.
  3. После schema change обязательно прогоняются generate и build.
  4. Backend использует Prisma через PrismaService, а не создаёт новые PrismaClient в произвольных местах.
  5. Frontend не должен тянуть Prisma runtime-код.
  6. Общие 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. Рекомендуемые следующие шаги

  1. Зафиксировать канонический data contract для Item, Lead, Review, EventLog.
  2. Документировать allowed read-path через $replica() и policy использования replica.
  3. Перевести Prisma seed/config на актуальный формат перед Prisma 7.
  4. Добавить отдельные интеграционные проверки на migrations и critical selects.
  5. Дальше строить аналитику поверх уже существующего Prisma/EventLog контура, а не вводить параллельный data stack без необходимости.