From b05615267d0d614aba2e294a27c6f9c3401cdad4 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.py | 23 +++++++++++- tests/integration_tests/test_matchmaker.py | 43 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/server/ladder_service.py b/server/ladder_service.py index 0b0375ef8..b4b2e731e 100644 --- a/server/ladder_service.py +++ b/server/ladder_service.py @@ -349,11 +349,30 @@ async def handle_match( await self.start_game(s1.players, s2.players, queue) except OfferTimeoutError: + unready_players = list(offer.get_unready_players()) self._logger.info( "Match failed to start. Some players did not ready up in time: %s", - list(player.login for player in offer.get_unready_players()) + [player.login for player in unready_players] ) - # TODO: Unmatch and return to queue + msg = {"command": "match_cancelled"} + for player in all_players: + player.write_message(msg) + + # Return any player that accepted the match back to the queue + # TODO: make this work with parties + for player in s1.players: + if player in unready_players: + await self.cancel_search(player) + else: + s1.unmatch() + asyncio.create_task(queue.search(s1)) + + for player in s2.players: + if player in unready_players: + await self.cancel_search(player) + else: + s2.unmatch() + asyncio.create_task(queue.search(s2)) except Exception as e: self._logger.exception( "Error processing match between searches %s, and %s: %s", diff --git a/tests/integration_tests/test_matchmaker.py b/tests/integration_tests/test_matchmaker.py index 1cf0869b6..b3c20de68 100644 --- a/tests/integration_tests/test_matchmaker.py +++ b/tests/integration_tests/test_matchmaker.py @@ -146,6 +146,49 @@ async def test_game_matchmaking_start(lobby_server, database): assert row["place"] is not None +@fast_forward(100) +async def test_game_matchmaking_search_after_timeout(lobby_server, database): + proto1 = await queue_player_for_matchmaking( + ('ladder1', 'ladder1'), + lobby_server + ) + proto2 = await queue_player_for_matchmaking( + ('ladder2', 'ladder2'), + lobby_server + ) + + 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"}) + + # So the match times out + await read_until_command(proto1, "match_cancelled") + await read_until_command(proto2, "match_cancelled") + + # At this point the search for player 2 should be cancelled, but player 1 + # should still be in the queue + msg = await read_until_command(proto2, "search_info") + assert msg == { + "command": "search_info", + "queue_name": "ladder1v1", + "state": "stop" + } + + # 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): proto1, proto2 = await queue_players_for_matchmaking(lobby_server)