private void CleanPendingLists(object sender, ElapsedEventArgs e)
        {
            var matchesToRemove = PendingMatches.Values.Where(p =>
            {
                var timespan = DateTime.Now - p.CreatedDate;

                return(timespan.TotalSeconds >= 30);
            }).ToList();

            foreach (var matchToRemove in matchesToRemove)
            {
                PendingMatches.Remove(matchToRemove.MatchID, out var _);
                _logger.LogInformation($"Removed match : {matchToRemove} from pending list as it's been not used for the last 30seconds.");
            }

            var usersToRemove = PendingGameUsers.Keys.Where(p =>
            {
                var timespan = DateTime.Now - p.CreatedTime;

                return(timespan.TotalSeconds >= 30);
            }).ToList();

            foreach (var userToRemove in usersToRemove)
            {
                PendingGameUsers.Remove(userToRemove, out var _);
                _logger.LogInformation($"Removed user : {userToRemove} from pending list as it's been not used for the last 30seconds.");
            }
        }
        /// <summary>
        /// User must come with proper matchID
        /// </summary>
        /// <param name="user"></param>
        public bool ConnectUser(GameUser user)
        {
            var hasPendingUser = PendingGameUsers.TryGetValue(user, out var pendingMatchID);

            if (hasPendingUser == false)
            {
                _logger.LogError($"No such pending user {user}");
                return(false);
            }

            var validMatch = Matches.TryGetValue(user.MatchID, out var match);

            if (validMatch == false)
            {
                //첫번째로 접속하려는 유저가 승격을 시킴.
                validMatch = PendingMatches.TryGetValue(user.MatchID, out match);
                if (validMatch)
                {
                    _logger.LogInformation($"Got from {match} from pending match");
                    Matches.TryAdd(user.MatchID, match);
                }
                else
                {
                    _logger.LogError($"Failed to connect {user} as Match {user.MatchID} doesn't exist");
                    return(false);
                }
            }
            else
            {
                _logger.LogInformation($"Got from {match} from normal match list");
            }

            match.Players.TryAdd(user.ConnectionID, user);

            _logger.LogInformation($"{user} is connected with connectionID : {user.ConnectionID} who is joining {match}");

            if (UserConnections.ContainsKey(user) == false)
            {
                UserConnections.AddOrUpdate(user, user.ConnectionID, (existingUser, existingConnectionId) =>
                {
                    existingUser.MatchID = match.MatchID;
                    //Update connectionId
                    existingUser.ConnectionID = user.ConnectionID;

                    return(user.ConnectionID);
                });
            }
            else
            {
                _logger.LogWarning($"Duplicate connection with ID:{user.ConnectionID} and User:{user}");
            }

            //If all done successfully, then remove pending list.
            PendingMatches.TryRemove(pendingMatchID, out var _);
            PendingGameUsers.TryRemove(user, out var _);

            return(true);
        }
        private bool TryAddToPendingUsers(GameUser user, string matchID)
        {
            user.CreatedTime = DateTime.Now;

            var pendingUser = PendingGameUsers.Keys.FirstOrDefault(p => p.ID == user.ID);

            //Update if already exists.
            if (pendingUser != null)
            {
                pendingUser.CreatedTime = DateTime.Now;
                return(true);
            }

            var result = PendingGameUsers.TryAdd(user, matchID);

            return(result);
        }
        private bool TryRemovePendingUserByID(Guid id, out GameUser removedUser)
        {
            var pendingUser = PendingGameUsers.Keys.FirstOrDefault(p => p.ID == id);

            if (pendingUser == null)
            {
                removedUser = null;
                return(false);
            }

            var timespan = DateTime.Now - pendingUser.CreatedTime;

            if (timespan.TotalSeconds >= 10)
            {
                PendingGameUsers.TryRemove(pendingUser, out var _);

                removedUser = pendingUser;
                return(true);
            }

            removedUser = null;
            return(false);
        }