Document Orleans hosting and enable Actions for the repo
CI / test (push) Failing after 3s
Details
CI / test (push) Failing after 3s
Details
This commit is contained in:
parent
6c0a6be872
commit
4888983816
|
|
@ -18,7 +18,7 @@
|
|||
| Мета-API: JWT, коллекция, колоды, магазин, история, реплеи | готово |
|
||||
| CI (Forgejo Actions) | workflow добавлен, runner нужно привязать |
|
||||
| EF-миграции | готово (`InitialCreate`) |
|
||||
| Orleans | не начато |
|
||||
| Orleans | готово: silo + `MatchActorGrain`, включается `Orleans:Enabled` |
|
||||
| Клиент и лаунчер | не начато |
|
||||
|
||||
## Требования
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ MVP: бустер **BT01** + триал-деки **TD01/TD02** — 94 карты
|
|||
|
||||
Стек:
|
||||
|
||||
- сервер — **.NET 10**, планируются **Orleans**, PostgreSQL, Redis;
|
||||
- сервер — **.NET 10**, **Orleans** (опционально), PostgreSQL, Redis;
|
||||
- клиент — **Unity 6** (ещё не начат);
|
||||
- лаунчер — **WPF** (ещё не начат);
|
||||
- контент — YAML + C#-скрипты карт;
|
||||
|
|
@ -38,7 +38,7 @@ MVP: бустер **BT01** + триал-деки **TD01/TD02** — 94 карты
|
|||
|
||||
| Проверка | Результат |
|
||||
|---|---|
|
||||
| Тесты | **173/173** (131 правила/контракты + 42 сервер) |
|
||||
| Тесты | **174/174** (131 правила/контракты + 43 сервер) |
|
||||
| `validate` | 0 ошибок, 0 предупреждений |
|
||||
| `translations check` | 94/94 |
|
||||
| `stress 1000` | 1000/1000 партий, 0 ошибок |
|
||||
|
|
@ -71,7 +71,7 @@ dotnet run --project server\src\Vanguard.Cli -- stress 1000
|
|||
|
||||
```
|
||||
Пройден! : не пройдено 0, пройдено 131 (Vanguard.Rules.Tests)
|
||||
Пройден! : не пройдено 0, пройдено 42 (Vanguard.Server.Tests)
|
||||
Пройден! : не пройдено 0, пройдено 43 (Vanguard.Server.Tests)
|
||||
OK: ошибок 0, предупреждений 0
|
||||
Переведено: 94/94
|
||||
Партий: 1000, завершено: 1000, ошибок: 0
|
||||
|
|
@ -231,7 +231,9 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
инстансами), иначе — из памяти.
|
||||
- **`IMatchGrain`**: 1 матч = 1 экземпляр, все входы (интенты, подключения,
|
||||
тики) проходят через один семафор; внутри нет ни ASP.NET Core, ни WebSocket —
|
||||
только `IMatchConnection`. Orleans-хостинг подключается поверх контракта.
|
||||
только `IMatchConnection`. Orleans-хост (`MatchActorGrain`) подключается
|
||||
поверх того же контракта; соединения живут в `IMatchConnectionRegistry`,
|
||||
чтобы состояние грана оставалось сериализуемым.
|
||||
- **WebSocket** `/game`: handshake, MessagePack, `intentId`, idempotency,
|
||||
`eventSeq`, `resync`, heartbeat (20 с простоя → ping, ещё 20 с без ответа
|
||||
→ `4408`), реконнект, захват сессии (`4409`), rate limit 16 интентов/с.
|
||||
|
|
@ -254,6 +256,12 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
- **Конфигурация**: `Storage:Provider` = `None` / `Memory` / `Postgres`,
|
||||
`Storage:ConnectionString`; `Redis:Configuration`. `Memory` — EF InMemory
|
||||
для тестов, `Postgres` — постоянное хранилище.
|
||||
- **Orleans**: `Orleans:Enabled` (`false` по умолчанию, `true` в compose).
|
||||
Включённый режим поднимает silo с localhost-clustering в том же процессе;
|
||||
`MatchActorGrain` держит доменный `MatchGrain`, `IMatchConnectionRegistry`
|
||||
остаётся в процессе. Граны `[KeepAlive]`: WebSocket нельзя потерять при
|
||||
выгрузке. Один silo на инстанс; для нескольких реплик нужен настоящий
|
||||
кластер и внешний реестр соединений. Тест кластера — `OrleansMatchTests`.
|
||||
- **Docker**: `Dockerfile` + `docker-compose.yml` поднимают postgres, redis
|
||||
(AOF) и сервер; `/health` на `http://localhost:8080` (порт меняется
|
||||
через `VANGUARD_PORT`, адрес WebSocket — `VANGUARD_WS_URL`).
|
||||
|
|
@ -261,7 +269,7 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
`translations check` на push/PR. Workflow добавлен, но home-runner
|
||||
зарегистрирован на другой репозиторий: для этого репозитория нужно
|
||||
включить Actions и привязать runner.
|
||||
- **Тесты серверного ядра** (33 из 42 в `Vanguard.Server.Tests`):
|
||||
- **Тесты серверного ядра** (34 из 43 в `Vanguard.Server.Tests`):
|
||||
- тикеты: одноразовость и TTL;
|
||||
- heartbeat: ping после 20 с простоя, закрытие через 20 с, сброс любым кадром;
|
||||
- grain: attach, чужое место, duplicate intent, чужой ход, сдача,
|
||||
|
|
@ -276,9 +284,11 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
`VANGUARD_TEST_POSTGRES` / `VANGUARD_TEST_REDIS`): реальные PostgreSQL
|
||||
и Redis, изъятие тикета, очередь;
|
||||
- E2E: два клиента играют полный матч по WebSocket и сходятся в победителе;
|
||||
обрыв и возврат по новому тикету с догоном состояния.
|
||||
обрыв и возврат по новому тикету с догоном состояния;
|
||||
- Orleans: грана инициализируется, принимает attach и интент, граница
|
||||
Orleans сериализуется (тестовый `TestCluster`).
|
||||
|
||||
Проверено на `ssh home`: 173/173 тестов, включая реальные PostgreSQL и Redis;
|
||||
Проверено на `ssh home`: 131 + 43 теста, включая реальные PostgreSQL и Redis;
|
||||
`docker compose up` поднимает стенд, матч создаётся через HTTP-очередь,
|
||||
а после `docker compose restart server` восстанавливается (`Recovery: 1 of 1`).
|
||||
|
||||
|
|
@ -322,7 +332,7 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
11 стартовых событий и кадр, рука противника пуста. После рестарта
|
||||
сервера матч восстановлен (`matches: 1`).
|
||||
|
||||
Счётчик `Vanguard.Server.Tests` вырос до 42: добавлены auth, мета-профиль,
|
||||
Счётчик `Vanguard.Server.Tests` вырос до 43: добавлены auth, мета-профиль,
|
||||
мета-E2E (онбординг → бустер → колода → матч → история → реплей),
|
||||
проверки реплея, явного выхода и истории/реплея после выхода.
|
||||
|
||||
|
|
@ -364,7 +374,7 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
/Profiles/ интерфейс MMR
|
||||
/Dockerfile
|
||||
/server/tests/Vanguard.Rules.Tests 131 тест
|
||||
/server/tests/Vanguard.Server.Tests 42 теста, включая E2E и внешние хранилища
|
||||
/server/tests/Vanguard.Server.Tests 43 теста, включая E2E и внешние хранилища
|
||||
/content/sets карты
|
||||
/content/trial-decks.yaml две триал-деки
|
||||
/content/pack_odds.yaml веса бустера
|
||||
|
|
@ -402,7 +412,7 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
в таком виде нельзя.
|
||||
- Состояние сервера: PostgreSQL — снапшот/журнал матчей, Redis — тикеты
|
||||
и очередь; без конфигурации работает in-memory. `IMatchGrain` отделён
|
||||
от транспорта, Orleans подключается поверх.
|
||||
от транспорта, Orleans подключается поверх и включается конфигом.
|
||||
- Rate limit — 16 интентов в секунду на соединение.
|
||||
- Скрытый MMR: старт 1000, Эло K = 32, casual рейтинг не меняет.
|
||||
- Аккаунты: BCrypt, access JWT 15 минут, refresh 30 дней с ротацией;
|
||||
|
|
@ -445,7 +455,7 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
своя рука и свой выбор полностью, у противника только количества
|
||||
и открытые зоны, seed и RNG не уходят.
|
||||
5. **[x] `Docker Compose`** — postgres, redis (AOF) и сервер; `/health`,
|
||||
порт через `VANGUARD_PORT`.
|
||||
порт через `VANGUARD_PORT`. Сервер запускается с `Orleans:Enabled=true`.
|
||||
6. **[x] Персистентность**:
|
||||
- PostgreSQL — заголовок матча + журнал интентов, восстановление повтором
|
||||
команд после рестарта, `MatchRecoveryService`;
|
||||
|
|
@ -456,14 +466,17 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
7. **Мета-API** — сделано: JWT, аккаунты, коллекция, колоды, магазин,
|
||||
экономика, онбординг, матчмейкинг по `deckId`, история и реплеи.
|
||||
`playerId` остался только как dev-режим при `Game:AllowDevQueue=true`.
|
||||
8. **Orleans** — заменить in-process регистр на настоящий silo и граны.
|
||||
`IMatchGrain` уже отделён от транспорта и ASP.NET Core; персистентность
|
||||
и проекция от хостинга не зависят.
|
||||
8. **[x] Orleans** — `MatchActorGrain` + `OrleansMatchAdapter`; silo
|
||||
включается `Orleans:Enabled=true`, в compose включён. `MatchGrain` остался
|
||||
доменным ядром, соединения вынесены в `IMatchConnectionRegistry`,
|
||||
`MatchActorGrain` восстанавливается из снапшота на активации. Покрыто
|
||||
`OrleansMatchTests` (тестовый кластер).
|
||||
|
||||
Критерий готовности серверного блока выполнен: два клиента играют полный
|
||||
матч по сети; kill клиента восстанавливается через новый тикет и
|
||||
`resumeFromSeq`; рестарт сервера восстанавливает матчи из PostgreSQL.
|
||||
Остались Orleans и привязка CI-runner.
|
||||
Остался только CI-runner: workflow есть, но home-runner привязан к другому
|
||||
репозиторию.
|
||||
|
||||
### 7.2. Мета-API
|
||||
|
||||
|
|
@ -520,7 +533,7 @@ Solution — **`server/Vanguard.slnx`**, не `.sln`.
|
|||
`GameConnection`, логин, коллекция, декбилдер, магазин, очередь,
|
||||
история и реплей. Сервер и мета-API готовы: `docs/protocol.md`,
|
||||
`docs/server-api.md`, `Vanguard.Shared`.
|
||||
4. Orleans и CI-runner — отдельные серверные долги, не блокируют клиент.
|
||||
4. CI-runner — отдельный серверный долг, не блокирует клиент; Orleans уже готов.
|
||||
5. После каждого блока: тесты, `validate`, `translations check`, коммит, push.
|
||||
6. Не ломать `Vanguard.Rules`: сервер должен зависеть от него, а не наоборот.
|
||||
|
||||
|
|
|
|||
|
|
@ -424,7 +424,8 @@ Redis: тикеты (`GETDEL`, TTL 60 с) и очередь (JSON + sorted set).
|
|||
История матча пишется, но реплей при `None` недоступен: строки матча нет.
|
||||
Для истории и реплеев нужен `Memory` или `Postgres`.
|
||||
- `EnsureCreated` используется только для InMemory; PostgreSQL — миграции.
|
||||
- Один процесс: Orleans-хостинг ещё впереди; `IMatchGrain` уже отделён.
|
||||
- Один процесс: Orleans включается `Orleans:Enabled`; по умолчанию матчи
|
||||
идут через in-process `MatchGrain`, в compose — через silo.
|
||||
- Нет магазина косметики, квестов, баттлпасса, Draft, друзей и чата.
|
||||
- Rate limit: 60/мин на auth, 300/мин на остальные мутирующие запросы.
|
||||
- Dev-очередь включается только `Game:AllowDevQueue=true` и не для production.
|
||||
|
|
|
|||
Loading…
Reference in New Issue