Files
image-platform/docs/development.md
S.Gromov 1c0e8277a3 feat: добавить генерацию image variants
- добавлен shared config presets, custom transforms и allowlist hosts
- реализованы Backend endpoints для assets, presets и variants
- добавлена orchestration через PostgreSQL, RabbitMQ, S3 и worker
- обновлён Gateway read-through flow с L1 cache и корректным Vary: Accept
- добавлена миграция resize_mode для variants lookup
- обновлены dev scripts, env template, lockfile и документация
2026-05-05 13:25:28 +03:00

225 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Локальная разработка
## Принцип
В Docker запускаем стабильную инфраструктуру. Кодовые сервисы запускаем нодой с hot reload.
Сейчас в Docker есть только:
- PostgreSQL;
- MinIO;
- MinIO bucket init;
- imgproxy dev instance;
- RabbitMQ.
`backend` уже умеет регистрировать assets и выполнять internal ensure. `gateway` уже ходит в Backend и держит L1 memory cache. `worker` уже читает RabbitMQ jobs, вызывает imgproxy и пишет variants в S3.
Gateway обязателен для Cloudinary-like поведения и интеграции с `next/image`.
## Запуск инфраструктуры
```bash
cp .env.example .env
pnpm install
pnpm infra:up
pnpm db:migrate
```
`.env` используется только локально и игнорируется git. Backend, Gateway, Worker и Drizzle scripts автоматически подхватывают его через Node `--env-file-if-exists`; в production эти переменные должны приходить из окружения процесса.
Проверить compose config:
```bash
pnpm infra:config
```
Остановить:
```bash
pnpm infra:down
```
Логи:
```bash
pnpm infra:logs
```
## Порты
| Сервис | URL |
|---|---|
| PostgreSQL | `localhost:5433` |
| MinIO API | `http://localhost:9000` |
| MinIO Console | `http://localhost:9001` |
| imgproxy | `http://localhost:18080` |
| RabbitMQ | `amqp://localhost:5672` |
| RabbitMQ Management | `http://localhost:15672` |
| Backend API | `http://localhost:3001/api` |
| Swagger | `http://localhost:3001/docs` |
| Admin | `http://localhost:5173` |
| Gateway | `http://localhost:8888` |
Если `localhost:8888` занят старым `image-gateway`, остановите старый stack или задайте `GATEWAY_PORT=8890` в `.env`.
## Backend
Запустить NestJS backend:
```bash
pnpm backend:dev
```
Проверки:
```bash
curl http://localhost:3001/api/health
open http://localhost:3001/docs
```
Зарегистрировать source image в dev mode:
```bash
curl -sS -X POST http://localhost:3001/api/assets \
-H 'content-type: application/json' \
-d '{"sourceUrl":"https://storage.yandexcloud.net/shared1318/img/1.jpg","publicId":"asset_demo"}'
```
Посмотреть business API:
```bash
curl -sS http://localhost:3001/api/presets
curl -sS http://localhost:3001/api/assets
curl -sS http://localhost:3001/api/assets/asset_demo
curl -sS http://localhost:3001/api/assets/asset_demo/variants
```
Явно поставить jobs на генерацию family variants без Gateway lazy request:
```bash
curl -sS -X POST http://localhost:3001/api/assets/asset_demo/variants \
-H 'content-type: application/json' \
-d '{"preset":"card","mode":"family"}'
```
## Database
Drizzle schema живёт в `packages/database/src/schema.ts`, миграции - в `packages/database/drizzle`.
Сгенерировать миграцию после изменения schema:
```bash
pnpm db:generate
```
Применить миграции к локальному PostgreSQL:
```bash
pnpm db:migrate
```
Открыть Drizzle Studio из корня проекта:
```bash
pnpm db:studio
```
Проверить database package:
```bash
pnpm db:typecheck
pnpm db:build
```
## Admin
Запустить React/Vite admin:
```bash
pnpm admin:dev
```
Открыть:
```bash
open http://localhost:5173
```
## Gateway
Gateway запускается нодой:
```bash
pnpm gateway:dev
```
Проверить gateway health:
```bash
curl http://localhost:8888/health
```
Проверить image origin route после запуска Backend и Worker:
```bash
curl -i "http://localhost:8888/images/asset_demo/v1/card?w=640&q=80&f=auto"
curl -i "http://localhost:8888/images/asset_demo/v1/avatar?f=auto"
curl -i "http://localhost:8888/images/asset_demo/v1/custom?w=777&h=333&q=72&fit=fill&f=webp"
```
Первый запрос должен пройти через Backend/RabbitMQ/Worker/imgproxy/S3 и вернуться с `x-image-platform-l1: MISS`. Повторный запрос должен вернуться из gateway L1 с `x-image-platform-l1: HIT`.
Статические presets сейчас лежат в `packages/image-config`:
- `card` - responsive, widths `320`, `640`, `960`.
- `hero` - responsive, widths `1280`, `1920`.
- `avatar` - fixed `256x256`.
Mock allowlist source hosts задаётся через `SOURCE_ALLOWED_HOSTS`. В dev по умолчанию разрешён `storage.yandexcloud.net`.
## Worker
Worker запускается нодой, объявляет RabbitMQ topology, слушает `image.generate-variant`, вызывает `imgproxy` и пишет готовый variant в S3.
```bash
pnpm worker:dev
```
Проверить worker package без запуска consumer:
```bash
pnpm worker:typecheck
pnpm worker:build
```
## Будущий dev flow
Текущая и будущая схема:
```text
React/Vite admin localhost:5173
-> NestJS backend localhost:3001
-> PostgreSQL localhost:5433
-> MinIO localhost:9000
-> RabbitMQ localhost:5672
worker node process
-> PostgreSQL
-> MinIO
-> RabbitMQ
-> imgproxy localhost:18080
Fastify gateway localhost:8888
-> L1 memory cache
-> Backend internal ensure endpoint
```
## imgproxy для разработки
В dev compose поднимается локальный `imgproxy`, опубликованный только на `127.0.0.1:18080`:
```env
IMGPROXY_UPSTREAM=http://localhost:18080
```
Для production `imgproxy` всё равно рассматривается как внешняя зависимость и может жить на отдельном мощном сервере.