This commit is contained in:
2026-10-11 13:26:38 +07:00
parent 74a45da402
commit 6f2b63511c
17 changed files with 1254 additions and 304 deletions
+44 -5
View File
@@ -350,7 +350,7 @@ RustFS и создать `<marker>.continue` в течение минуты. Buc
## Пакет результатов, версия 1 (ED-029, этап 9)
Это отдельный контракт: ZIP содержит ровно `manifest.json` и `results.json`,
без сценария и файлов. Серверное применение реализовано этапом 10; API/UI остаются этапом 11.
без сценария и файлов. Серверное применение реализовано этапом 10; API/UI описаны в этапе 11.
`game_results_package_service.NewGameResultsPackageService(repo, mode).Prepare(ctx,
gameID, output)` доступен только в `venue`, для существующей игры из готового
@@ -441,10 +441,10 @@ workspace. Стенд проверяет оба формата, свежую о
## Применение результатов онлайн (ED-029, этап 10)
`game_results_package_service.NewGameResultsApplyService(repo, privateStorage,
mode, sourceServer).Apply(ctx, input io.ReaderAt, size, initiatorID)` доступен
только при `mode="prod"`. Это серверный сервис без нового API/UI и развёртывания.
Возвращается закрытая запись реестра; будущий transport должен выдавать только
публичный результат операции.
mode, sourceServer).Apply(ctx, expectedGameID, input io.Reader, initiatorID)` доступен
только при `mode="prod"`. Положительный `expectedGameID` и совпадение с manifest
проверяются до поиска повтора и изменений. Возвращается закрытая запись реестра;
transport выдаёт только `gameID`, `packageID`, `appliedAt`.
Входные байты один раз сохраняются в приватный временный файл и проверяются
кодеком этапа 9; SHA-256 всего ZIP связывает повтор с этими же байтами.
@@ -518,3 +518,42 @@ Sequence-значения PostgreSQL не откатываются: больши
Перед поддержкой площадок с такими разрывами требуется расширить типы ID.
ZIP на 1 ГиБ, 100 клиентов и Wi-Fi этим этапом не проверяются. До завершения
этапа 11 и контрольного прогона используются только тестовые игры.
## Интерфейс возврата (ED-029, этап 11)
Организатор, администратор и разработчик используют два endpoint-а с Bearer JWT:
- `GET /api/games/{ID}/results-package/download` — только venue, завершённая
импортированная игра. Каждый запрос готовит свежий ZIP в приватном временном
файле, целиком проверяет подготовку и затем выдаёт `application/zip` с
`Content-Disposition`, `Content-Length`, `Cache-Control: no-store`. Очереди
и сохранённого пакета нет; файл удаляется при успехе, ошибке и отмене.
- `POST /api/games/{ID}/results-package/apply` — только prod, сырое тело
`application/zip` до 1 ГиБ, в том числе без `Content-Length`. Сервис один раз
сохраняет ограниченный поток с SHA-256 в файл 0600 и проверяет ZIP. Ответ:
`{ "gameID": 1, "packageID": "…", "appliedAt": "…" }`; закрытый реестр
не раскрывается. Повтор выдаёт исходное время применения.
Неверный пакет/игра — HTTP 400, превышение размера — 413, конфликт — 409,
временный отказ — 503. Прочие ошибки и авторизация следуют правилам приложения;
внутренние причины логируются на транспортной границе. Protobuf/OpenAPI описывают
операции; HTTP использует отдельные бинарные handlers, gRPC ограничен текущим
размером сообщений. Таймаут бинарных HTTP-операций — 30 минут.
В настройках завершённой venue-игры есть «Скачать результаты». В настройках
prod-игры блок «Возврат результатов с площадки» доступен и после исчезновения
офлайн-отметки. Форма проверяет один непустой `.zip` до 1 ГиБ и предупреждает
о замене команд, билетов, результатов и сценария, потере онлайн-правок и
сохранении оформления/музыки. Бинарный клиент обновляет авторизацию. Во время
запроса повтор заблокирован; любой принятый ZIP получает сообщение «Результаты
приняты». После успеха страница пересоздаётся и перечитывает данные; старые
ответы, формы, модальные окна и черновики редакторов удаляются.
Конфигурации nginx и reproxy допускают ZIP 1 ГиБ и долгие операции; работающие
серверы не обновляются. У reproxy лимит/таймауты общие для его маршрутов.
Контрольный тест: `python3 tests/venue/flow.py --apply --browser` — оба формата,
реальные PostgreSQL/RustFS, API и Firefox, свежий ZIP кнопкой, применение через
страницу prod, исправленный балл, перезапись онлайн-ответа, исходные ссылки и
билеты, сохранение оформления, снятие офлайн-отметки, повтор после перезапуска.
ZIP остаётся неподписанным; нагрузка, Wi-Fi и фактический ZIP 1 ГиБ не проверяются.