# x0gp server (PoC) Минимальный Go-сервер для сквозной проверки идеи x0gp: WebSocket-клиент (браузер) отправляет команды руля/газа, сервер гоняет упрощённую authoritative-физику на 60 Hz и шлёт снапшоты обратно. **Это PoC.** Без биллинга, без CV, без агента на машинке. WebSocket + race engine + Postgres (каталог tracks / cars) + Redis pub/sub. --- ## Архитектура PoC ``` browser -- WS(JSON) --> poc-server -- in-process --> RaceEngine (60 Hz tick) \-> Snapshot fan-out via Hub ``` См. [ARCHITECTURE.md](../ARCHITECTURE.md) и [PLAN.md](./PLAN.md) для общей картины и будущих фаз. --- ## Структура ``` server/ cmd/poc-server/main.go # точка входа, HTTP + WS, race engine tick internal/ config/ # env-конфиг transport/ # JSON-codec (PoC), envelope, типы сообщений control/ # authoritative race engine (tick 60 Hz, физика) realtime/ # WebSocket hub, fan-out, backpressure catalog/ # tracks + cars, интерфейс Store + in-memory cache seeddefs/ # Go-определения seed-данных (общие с SQL seed) storage/postgres/ # pgx pool, embedded миграции, PgStore migrations/ # 001_init.sql, 002_seed.sql scripts/genseed/ # утилита для перегенерации 002_seed.sql proto/ # формальная спецификация (proto3) client_server.proto server_agent.proto buf.yaml, buf.gen.yaml web/ # минимальный vanilla-JS клиент index.html, main.js, style.css Dockerfile # multi-stage, linux/arm64 для Orange Pi 5 Pro docker-compose.yml # dev stack: postgres+timescale, redis, prom, grafana Makefile # build, run, proto, test, docker, compose .gitignore go.mod ``` --- ## Быстрый старт (на Orange Pi 5 Pro) ### 1. Подготовка ```bash # Установить Go 1.26+ (если ещё не стоит). wget https://go.dev/dl/go1.26.4.linux-arm64.tar.gz sudo tar -C /usr/local -xzf go1.26.4.linux-arm64.tar.gz export PATH=$PATH:/usr/local/go/bin echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc go version # должно быть go1.26.x ``` ### 2. Клонирование и сборка ```bash git clone https://github.com//x0gp.git cd x0gp/server # Тянем зависимости и собираем бинарь под arm64. make tidy make build # -> bin/poc-server-linux-arm64 ``` ### 3. Запуск (минимальный) ```bash X0GP_DEV_MODE=true ./bin/poc-server-linux-arm64 ``` Открыть в браузере на той же машине: `http://localhost:8080/`. Подключиться через web-интерфейс — увидишь виртуальные машинки, которые гоняют по сцене, реагируя на команды. ### 4. Запуск полного dev-стека (через docker compose) ```bash make compose-up # поднимает postgres, redis, prometheus, grafana, api-gateway # api-gateway будет на http://localhost:8080 # grafana: http://localhost:3000 (admin/admin) make compose-down # остановить ``` ### 5. Деплой в Coolify (см. [../ops/HOME_SERVER.md](../ops/HOME_SERVER.md)) - Push репо на GitHub/Gitea. - В Coolify: New Resource → Application → подключить репо. - Build Pack: Dockerfile. - Port: 8080. - Env vars: `X0GP_DEV_MODE=true` для PoC. - Healthcheck path: `/health`. --- ## Конфигурация (env vars) | Variable | Default | Описание | |---|---|---| | `X0GP_HTTP_ADDR` | `:8080` | Адрес HTTP-сервера | | `X0GP_TICK_RATE` | `60` | Race engine tick (Гц) | | `X0GP_SNAPSHOT_RATE` | `30` | Snapshot fan-out (Гц) | | `X0GP_MAX_CLIENTS` | `100` | Лимит одновременных WS | | `X0GP_LOG_LEVEL` | `info` | `debug`/`info`/`warn`/`error` | | `X0GP_DEV_MODE` | `true` | PoC-режим: без auth, несколько клиентов | | `DATABASE_URL` | — | **обязательно**. Строка подключения к Postgres (например `postgres://x0gp:x0gp@localhost:5432/x0gp?sslmode=disable`). Сервер не стартует без неё. | --- ## WebSocket протокол Все кадры — JSON-объекты с полями `type`, `seq`, `ts_ms`, `payload`. См. [proto/client_server.proto](./proto/client_server.proto) — формальная спецификация для будущего бинарного protobuf-формата (MVP/prod). ### Пример: подключиться и поуправлять машинкой (из консоли) ```bash # Через websocat (apt install websocat). websocat ws://localhost:8080/ws # Ввести: {"type":"client_hello","payload":{"version":"0.1"}} {"type":"join_race","payload":{"car_slot":0,"car_name":"alice"}} {"type":"input_state","payload":{"steering":0.5,"throttle":0.8,"brake":0}} # ... крутить рулём и газом ``` Сервер сразу же начнёт присылать `race_snapshot` (30 Гц) с позициями всех машинок. --- ## Метрики и логи - `/health` — healthcheck (JSON). - `/stats` — текущие connection count, snapshot drops, race phase. - `/metrics` — Prometheus metrics (будет в S1). - Логи: JSON в stdout (slog), удобно для Loki/Promtail. --- ## Хранилище (Postgres + TimescaleDB) Каталог (tracks / cars) хранится в Postgres. Миграции лежат в `internal/storage/postgres/migrations/*.sql`, встроены через `//go:embed` и применяются автоматически при старте сервера (см. `internal/storage/postgres/postgres.go:Migrate`). Уже применённые миграции отслеживаются в таблице `schema_migrations`. - `001_init.sql` — схема: `tracks`, `track_waypoints`, `track_tags`, `cars`, плюс `CREATE EXTENSION timescaledb` (для будущего телеметрического hypertable в S2). - `002_seed.sql` — system-данные: 3 трассы (`oval-classic`, `figure-eight`, `sprint-straight`) и 2 машины (`compact-1-27-touring`, `compact-1-27-formula`). Сидовые Go-определения лежат в `internal/catalog/seeddefs`; чтобы перегенерировать SQL, см. `scripts/genseed`. Локальный стек поднимается через `make compose-up` (см. `docker-compose.yml`). Сервер стартует **fail-fast**: если `DATABASE_URL` не задан или БД недоступна, процесс завершается с ошибкой и кодом 1 — без БД каталог работать не будет. ## Команды разработки ```bash make tidy # go mod tidy make build # сборка make run # локальный запуск (dev) make test # go test ./... make lint # go vet + golangci-lint make proto # регенерация proto/gen/ (через Docker buf) make docker # собрать api-gateway image make compose-up # поднять dev стек make compose-down # опустить dev стек make clean # rm -rf bin/ ``` --- ## Что дальше См. [PLAN.md](./PLAN.md) и [../ARCHITECTURE.md](../ARCHITECTURE.md): - **S1 (MVP)**: добавить Postgres, Redis, JWT-auth, лобби. - **S2**: overhead-CV на NPU Orange Pi, телеметрия в TimescaleDB. - **S3**: биллинг через ЮKassa. - **S4**: турниры. --- ## Лицензия TBD (предлагается Apache 2.0).