Skip to content

Map pick: always hand out a CRC, and make sure the CDN has the map - #61

Open
bill-rich wants to merge 2 commits into
f4hy:mainfrom
bill-rich:pr/map-transfer-radarvan-pick
Open

Map pick: always hand out a CRC, and make sure the CDN has the map#61
bill-rich wants to merge 2 commits into
f4hy:mainfrom
bill-rich:pr/map-transfer-radarvan-pick

Conversation

@bill-rich

Copy link
Copy Markdown
Contributor

Pairs with GeneralsZulu/LegacyGameClient#84 - the game client cannot fetch a map it does not have without a CRC, so both need to land.

The client keys a map download off the CRC that /api/map_vote/{n}/choose returns. That CRC was null whenever the map had never been played and had no stored CRC, which disabled the whole download path and left the host with GUI:MapVoteNotFound.

  • resolve_map_crc now chains the old sources (stored MapData.crc, then a replay of a match played on the map) with a new one: the raw .map bytes we already host in S3, computing the SAGE CRC and writing it back to MapData. A map nobody has played now gets a CRC.
  • Sync-on-pick: the map is pushed to cncstats before the pick is returned, so the CDN actually has what we just handed out a key for.
  • Scheduler job (6h) so the CDN stops drifting stale. push_unsynced_maps is now shared by the job and the existing admin route.
  • map_contents_mask is returned only when we populated the CDN entry on that call. When cncstats already had the map, its asset inventory is not ours to describe, so the field stays null and the client keeps its ask-for-everything default.

A map with no resolvable CRC is still offered in the draw and simply returns a null CRC, exactly as before - the client falls back to the legacy launch-time P2P transfer. (An earlier revision dropped such maps from the pool; that was wrong, because a transient S3 error would then silently shrink the vote pool.)

pytest tests/ -q: 225 passed, 5 skipped, 0 failed.
make check (ruff + mypy): clean.

Both players' clients upload their own recording of the same match at
game end, and the files differ byte-wise so the hash dedup never catches
them. register_match's check-then-insert then either raises IntegrityError
(loser inserts before the winner commits) or silently returns the existing
row and the caller posts the win prediction a second time.

register_match now returns (match, created), flushes inside a try, and on
IntegrityError rolls back and returns the concurrently inserted row with
created=False. upload_replay and the batch register path only send the
prediction notify when created is True. First upload to land still owns
the match row; the second replay file is stored as before.
choose_map only set chosen_map_crc when missing_maps.crc_for_map() could
resolve one, i.e. from a stored MapData.crc or from a replay of a match already
played on that map. A map that has never been played and never got a CRC came
back with chosen_map_crc=null, and the CRC is the only key the game client has
to fetch a map it doesn't own - so a host that lacked the picked map could not
install it and the pick failed in the lobby.

- resolve_map_crc chains the existing sources with the .map bytes we host in
  S3 (computing the SAGE CRC from them and writing it back to MapData), so any
  map we can supply has a CRC.
- Ensure the map is on cncstats before returning it, and add the same push to
  the scheduler - it was only ever a manual admin route, so the CDN drifted
  stale and a picked map could be one nobody could download.
- Report map_contents_mask when we populated the CDN entry ourselves, so the
  client asks for the assets that exist instead of probing all seven.

A map whose CRC still cannot be resolved remains a legal pick: chosen_map_crc
is null and the client falls back to the launch-time P2P transfer from the
host, which is exactly what it did before. Dropping such maps from the draw
would let a transient S3 or credentials error silently shrink the vote pool.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant