- добавлен 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 и документация
225 lines
5.8 KiB
Markdown
225 lines
5.8 KiB
Markdown
# Локальная разработка
|
||
|
||
## Принцип
|
||
|
||
В 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` всё равно рассматривается как внешняя зависимость и может жить на отдельном мощном сервере.
|