Add city gameplay, snapshot migrations, administration and Compose operations

This commit is contained in:
mrleo1nid committed 2026-10-30 22:17:17 +03:00
1 parent 3b1fcd996a
commit 85df37c26e
24 files changed
+1042 -55

No files matched your search

+75
View File
@@ -0,0 +1,75 @@
# Запуск через Compose
Из корня репозитория, с работающим Docker Engine:
```sh
cp .env.example .env
docker compose config --quiet
docker compose build
# Необязательно: подготовить город из локальной OSM-выгрузки.
docker compose run --rm --no-deps app node --import tsx tools/demo.ts
docker compose up -d --wait
```
Открыть `http://localhost:3000/?play`. Можно создать город через интерфейс.
Города и сохранения находятся в отдельных постоянных томах `cities` и `saves`.
Пересборка и `docker compose down` сохраняют тома. `down -v` удаляет их.
Существующий каталог города нельзя перезаписывать, пока на него ссылаются комнаты.
Приложение работает от пользователя `node`, с лимитами памяти, CPU,
процессов и ротацией логов. Значения `.env.example` рассчитаны на старт с
1000 жителями; миллион жителей и пять комнат требуют замера и настройки.
Порт по умолчанию доступен локально. Для внешнего доступа измените
`CITYGEN_HOST_IP` или используйте HTTPS reverse proxy с WebSocket.
Встроенный лимит создания видит IP TCP-соединения, поэтому за прокси он
общий для всех посетителей; недоверенные X-Forwarded-For не используются.
Остановка посылает SIGTERM; сервер завершает комнаты и ждёт запись снимков
(до 120 секунд). Перед обновлением:
```sh
docker compose stop
# Сделать резервную копию ОБОИХ томов средствами Docker-хоста.
docker compose build
docker compose up -d --wait
```
Проверка: `docker compose ps`, `docker compose logs --tail=100 app`,
`curl --fail http://localhost:3000/health`. Миграция комнат v1→v2 выполняется
при открытии комнаты; неизвестная версия остаётся на диске с ошибкой.
Квота `CITYGEN_SAVE_QUOTA_BYTES` включает все снимки и временный новый файл
до ротации: оставьте запас минимум на один полный снимок. При переполнении
запись отклоняется, прежние снимки сохраняются. Квота относится к снимкам;
объём городов ограничивайте средствами Docker-хоста.
## Администрирование
Задать `CITYGEN_ADMIN_TOKEN` случайной строкой минимум из 32 символов в `.env`
и пересоздать контейнер. Пустое значение отключает API. `.env` игнорируется Git
и не попадает в build context. `/?admin` показывает комнаты, использование
диска и ошибки несовместимых снимков, позволяет сохранить активную комнату.
Ответ приходит после записи. Токен остаётся только в памяти страницы.
API: `GET /api/admin`, `POST /api/admin/rooms/{id}/checkpoint`,
заголовок `Authorization: Bearer <token>`. Привилегии оператора не выдаются
игрокам и создателям комнат. Удаление миров/городов через API не предусмотрено.
## Мониторинг
```sh
docker compose --profile monitoring up -d --wait
```
Prometheus на `http://localhost:9090` опрашивает `/metrics` каждые 5 секунд,
хранит до 7 дней / 1 ГБ. `alerts.yml` содержит правила недоступности,
тиков дольше 50 мс и ошибок сохранения. Предупреждения видны в Prometheus;
внешние уведомления требуют отдельного Alertmanager. Зафиксирована
[версия 3.15.1](https://github.com/prometheus/prometheus/releases/tag/v3.15.1).
Метрики: комнаты/игроки, сущности, последний/максимальный тик,
байты рассылки, ошибки и последний успешный тик сохранения. Ошибки снимков,
медленные тики, запуск/остановка пишутся JSON-строками в stderr.
Без Engine можно проверить `docker compose --profile monitoring config --quiet`.
Полный smoke-test контейнера после запуска: `/health`, вход двух клиентов,
команда «Обед», остановка/запуск и проверка восстановленного состояния.
+23
View File
@@ -0,0 +1,23 @@
groups:
- name: citygen
rules:
- alert: CitygenDown
expr: up{job="citygen"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: Citygen cannot be scraped
- alert: CitygenSlowTick
expr: citygen_room_tick_seconds > 0.05
for: 30s
labels:
severity: warning
annotations:
summary: Room tick exceeds 50 ms
- alert: CitygenSaveFailure
expr: increase(citygen_room_save_errors_total[5m]) > 0
labels:
severity: critical
annotations:
summary: Room snapshot failed; check disk quota and logs
+8
View File
@@ -0,0 +1,8 @@
global:
scrape_interval: 5s
rule_files:
- /etc/prometheus/alerts.yml
scrape_configs:
- job_name: citygen
static_configs:
- targets: [app:3000]