in GameLiftPlugin/Resources/CloudFormation/scenario4_containers_flexmatch/functions/main/requests/flexmatch_status_poller.py [0:0]
def handler(event, context):
"""
Finds all non-terminal matchmaking requests and poll for their status. It is recommended by GameLift
to regularly poll for ticket status at a low rate.
See: https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-client.html#match-client-track
:param event: lambda event, not used by this function
:param context: lambda context, not used by this function
:return: None
"""
lambda_start_time = round(time.time())
print(f"Polling non-terminal matchmaking tickets. Lambda start time: {lambda_start_time}")
matchmaking_request_table_name = os.environ['MatchmakingRequestTableName']
dynamodb = boto3.resource('dynamodb')
matchmaking_request_table = dynamodb.Table(matchmaking_request_table_name)
gamelift = boto3.client('gamelift')
matchmaking_requests = matchmaking_request_table.scan(
Limit=NON_TERMINAL_REQUEST_QUERY_LIMIT,
FilterExpression=And(Attr('TicketStatus').eq(MATCHMAKING_STARTED_STATUS),
Attr('LastUpdatedTime').lt(lambda_start_time - MIN_TIME_ELAPSED_BEFORE_UPDATE_IN_SECONDS))
)
if matchmaking_requests['Count'] <= 0:
print("No non-terminal matchmaking requests found")
for matchmaking_requests in partition(matchmaking_requests['Items'], MAX_PARTITION_SIZE):
ticket_id_to_request_mapping = {request['TicketId']: request for request in matchmaking_requests}
describe_matchmaking_result = gamelift.describe_matchmaking(
TicketIds=list(ticket_id_to_request_mapping.keys())
)
ticket_list = describe_matchmaking_result['TicketList']
if len(ticket_list) != len(matchmaking_requests):
print(f"Resulting TicketList length: {len(ticket_list)} from DescribeMatchmaking "
f"does not match the request size: {len(matchmaking_requests)}")
for ticket in ticket_list:
ticket_id = ticket['TicketId']
ticket_status = ticket['Status']
matchmaking_request_status = to_matchmaking_request_status(ticket_status)
matchmaking_request = ticket_id_to_request_mapping[ticket_id]
player_id = matchmaking_request['PlayerId']
start_time = matchmaking_request['StartTime']
last_updated_time = matchmaking_request['LastUpdatedTime']
try:
attribute_updates = {
'LastUpdatedTime': {
'Value': lambda_start_time
}
}
if ticket_status in ['COMPLETED', 'FAILED', 'TIMED_OUT', 'CANCELLED']:
print(f'Ticket: {ticket_id} status was updated to {ticket_status}')
attribute_updates.update({
'TicketStatus': {
'Value': matchmaking_request_status
}
})
if ticket_status == 'COMPLETED':
# parse the playerSessionId
matched_player_sessions = ticket.get('GameSessionConnectionInfo', {}).get('MatchedPlayerSessions')
player_session_id = None
if matched_player_sessions is not None and len(matched_player_sessions) == 1:
player_session_id = matched_player_sessions[0].get('PlayerSessionId')
attribute_updates.update({
'IpAddress': {
'Value': ticket.get('GameSessionConnectionInfo', {}).get('IpAddress')
},
'DnsName': {
'Value': ticket.get('GameSessionConnectionInfo', {}).get('DnsName')
},
'Port': {
'Value': str(ticket.get('GameSessionConnectionInfo', {}).get('Port'))
},
'GameSessionArn': {
'Value': str(ticket.get('GameSessionConnectionInfo', {}).get('GameSessionArn'))
},
'PlayerSessionId': {
'Value' : str(player_session_id)
}
})
else:
print(f'No updates to ticket: {ticket_id} compared to '
f'{lambda_start_time - last_updated_time} seconds ago')
matchmaking_request_table.update_item(
Key={
'PlayerId': player_id,
'StartTime': start_time
},
AttributeUpdates=attribute_updates,
Expected={
'TicketStatus': {
'Value': MATCHMAKING_STARTED_STATUS,
'ComparisonOperator': 'EQ'
}
}
)
except ClientError as e:
error_code = e.response['Error']['Code']
if error_code == 'ConditionCheckFailedException':
print(f"Ticket: {ticket_id} status has been updated (likely by MatchMakerEventHandler). "
f"No change is made")
continue
raise e