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 и 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. Подготовка
# Установить 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. Клонирование и сборка
git clone https://github.com/<you>/x0gp.git
cd x0gp/server
# Тянем зависимости и собираем бинарь под arm64.
make tidy
make build # -> bin/poc-server-linux-arm64
3. Запуск (минимальный)
X0GP_DEV_MODE=true ./bin/poc-server-linux-arm64
Открыть в браузере на той же машине: http://localhost:8080/.
Подключиться через web-интерфейс — увидишь виртуальные машинки, которые
гоняют по сцене, реагируя на команды.
4. Запуск полного dev-стека (через docker compose)
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)
- 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 — формальная спецификация для будущего бинарного protobuf-формата (MVP/prod).
Пример: подключиться и поуправлять машинкой (из консоли)
# Через 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 — без БД каталог работать не будет.
Команды разработки
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 и ../ARCHITECTURE.md:
- S1 (MVP): добавить Postgres, Redis, JWT-auth, лобби.
- S2: overhead-CV на NPU Orange Pi, телеметрия в TimescaleDB.
- S3: биллинг через ЮKassa.
- S4: турниры.
Лицензия
TBD (предлагается Apache 2.0).