fix(game): #59 — per-command rejection on PUT /api/v1/order
Validation of a player's order now applies every command against a transient game-state snapshot and records the per-command outcome (cmdApplied, cmdErrorCode) in each command's meta. The order is persisted even when some commands are rejected, and the response is 202 + UserGamesOrder so clients can surface the partial failure without the chain collapsing into "downstream service is unavailable". Pkg/error consts are reshelved onto three explicit ranges with a package doc and helpers (IsInternalCode/IsInputCode/IsGameStateCode): 1xxx internal/server (500/501), 2xxx structural input (400), 3xxx game-state per-command rejection (400 when escaping HTTP, otherwise recorded as cmdErrorCode). Two pre-existing typos fixed mechanically (ErrBeakGroupNumberNotEnough -> ErrBreakGroupNumberNotEnough, ErrRaceExinct -> ErrRaceExtinct) along with all callsites. Engine errorResponse maps *GenericError by shelf rather than mapping everything to 500. The Quit-not-last structural check in Controller.ValidateOrder is preserved and its type assertion fixed (was a value assertion against a pointer-typed command, so the check silently never fired). Backend, gateway and UI are unchanged — they were already correct on the 202 path; only the engine collapsing per-command rejection into 500 was needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -666,6 +666,20 @@ Backend не парсит содержимое payload команд или пр
|
||||
FB-форму только чтобы транскодировать wire-формат; per-command-
|
||||
семантика живёт в движке.
|
||||
|
||||
Специально для `user.games.order` движок валидирует каждую команду
|
||||
приказа на транзиентном слепке текущего состояния игры и записывает
|
||||
итог по каждой команде в её мету (`cmdApplied`, `cmdErrorCode`) в
|
||||
том же ответе `UserGamesOrder`. Приказ сохраняется с этими
|
||||
per-command-вердиктами даже если часть команд была отклонена —
|
||||
например, удаление команды «создать класс корабля X» из приказа,
|
||||
в котором остаётся «строить X», приводит к тому, что вторая команда
|
||||
возвращается с `cmdErrorCode` «сущность не существует», а остальные
|
||||
команды приказа остаются сохранёнными, и ответ остаётся
|
||||
`202 Accepted`. `400` возвращается только для структурных отказов
|
||||
на уровне приказа (`quit` не последняя команда, неизвестный
|
||||
command type, малформированный вход); `500` — только для реальных
|
||||
внутренних сбоев движка.
|
||||
|
||||
### 6.3 Окно хода и auto-pause
|
||||
|
||||
Запущенная игра постоянно чередуется между окном приёма команд
|
||||
|
||||
Reference in New Issue
Block a user