From 378ba27e909aac764a848c2ef8488e6ff9bbcdcd Mon Sep 17 00:00:00 2001 From: Askaholic Date: Sat, 20 Jun 2020 00:18:11 -0800 Subject: [PATCH] Restart search automatically after a timeout --- server/ladder_service/ladder_service.py | 19 +++++++++-- tests/integration_tests/test_matchmaker.py | 39 ++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/server/ladder_service/ladder_service.py b/server/ladder_service/ladder_service.py index 8506ff3f2..1f75d251d 100644 --- a/server/ladder_service/ladder_service.py +++ b/server/ladder_service/ladder_service.py @@ -487,6 +487,8 @@ async def confirm_match( offer = self.create_match_offer(all_players) offer.write_broadcast_update() await offer.wait_ready() + + await self.start_game(s1.players, s2.players, queue) except OfferTimeoutError: unready_players = list(offer.get_unready_players()) assert unready_players, "Unready players should be non-empty if offer timed out" @@ -502,11 +504,24 @@ async def confirm_match( player.state = PlayerState.IDLE player.write_message(msg) - # TODO: Unmatch and return to queue + # Return any player that accepted the match back to the queue + # TODO: make this work with parties + for search in (s1, s2): + for player in search.players: + if player in unready_players: + self.cancel_search(player) + else: + search.unmatch() + player.state = PlayerState.SEARCHING_LADDER + asyncio.create_task(queue.search(search)) self.violation_service.register_violations(unready_players) - await self.start_game(s1.players, s2.players, queue) + except Exception as e: + self._logger.exception( + "Error processing match between searches %s, and %s: %s", + s1, s2, e + ) def create_match_offer(self, players: Iterable[Player]): offer = MatchOffer( diff --git a/tests/integration_tests/test_matchmaker.py b/tests/integration_tests/test_matchmaker.py index 0f74d42d2..f9d2589ec 100644 --- a/tests/integration_tests/test_matchmaker.py +++ b/tests/integration_tests/test_matchmaker.py @@ -184,6 +184,45 @@ async def test_game_matchmaking_start_while_matched(lobby_server): assert msg["text"].startswith("Can't join a queue while ladder1 is in") +@fast_forward(100) +async def test_game_matchmaking_search_after_timeout(lobby_server): + _, proto1 = await queue_player_for_matchmaking( + ("ladder1", "ladder1"), + lobby_server, + "ladder1v1" + ) + _, proto2 = await queue_player_for_matchmaking( + ("ladder2", "ladder2"), + lobby_server, + "ladder1v1" + ) + + await read_until_command(proto1, "match_info") + await read_until_command(proto2, "match_info") + + # Only player 1 readies up + await proto1.send_message({"command": "match_ready"}) + + await read_until_command(proto1, "match_info", timeout=5) + await read_until_command(proto2, "match_info") + + # So the match times out + await read_until_command(proto1, "match_cancelled", timeout=40) + await read_until_command(proto2, "match_cancelled") + + # Player 2 joins the queue again + await proto2.send_message({ + "command": "game_matchmaking", + "state": "start", + "faction": "seraphim", + "mod": "ladder1v1" + }) + + # The players should match + await read_until_command(proto1, "match_info") + await read_until_command(proto2, "match_info") + + @fast_forward(120) async def test_game_matchmaking_timeout(lobby_server, game_service): _, proto1, _, proto2 = await queue_players_for_matchmaking(lobby_server)