From e0d647398697e9acdff1040bef80bcc60ffdc495 Mon Sep 17 00:00:00 2001 From: Ant Zucaro Date: Sun, 13 Nov 2016 19:45:20 -0500 Subject: [PATCH] Improve server matching. The old code would attempt to match on hashkey OR name, depending on what information was provided. The new version will search on both at the same time by using the builder pattern on the query. --- xonstat/views/submission.py | 128 +++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/xonstat/views/submission.py b/xonstat/views/submission.py index 75c0f01..a7ca8d2 100644 --- a/xonstat/views/submission.py +++ b/xonstat/views/submission.py @@ -350,86 +350,94 @@ def update_fastest_cap(session, player_id, game_id, map_id, captime, mod): session.flush() -def get_or_create_server(session, name, hashkey, ip_addr, revision, port, - impure_cvars): +def update_server(server, name, hashkey, ip_addr, port, revision, impure_cvars): """ - Find a server by name or create one if not found. Parameters: - - session - SQLAlchemy database session factory - name - server name of the server to be found or created - hashkey - server hashkey - ip_addr - the IP address of the server - revision - the xonotic revision number - port - the port number of the server - impure_cvars - the number of impure cvar changes + Updates the server in the given DB session, if needed. + + :param server: The found server instance. + :param name: The incoming server name. + :param hashkey: The incoming server hashkey. + :param ip_addr: The incoming server IP address. + :param port: The incoming server port. + :param revision: The incoming server revision. + :param impure_cvars: The incoming number of impure server cvars. + :return: bool """ - server = None - + # ensure the two int attributes are actually ints try: port = int(port) except: port = None - try: + try: impure_cvars = int(impure_cvars) except: impure_cvars = 0 - # finding by hashkey is preferred, but if not we will fall - # back to using name only, which can result in dupes - if hashkey is not None: - servers = session.query(Server).\ - filter_by(hashkey=hashkey).\ - order_by(expr.desc(Server.create_dt)).limit(1).all() - - if len(servers) > 0: - server = servers[0] - log.debug("Found existing server {0} by hashkey ({1})".format( - server.server_id, server.hashkey)) - else: - servers = session.query(Server).\ - filter_by(name=name).\ - order_by(expr.desc(Server.create_dt)).limit(1).all() + updated = False + if name and server.name != name: + server.name = name + updated = True + if hashkey and server.hashkey != hashkey: + server.hashkey = hashkey + updated = True + if ip_addr and server.ip_addr != ip_addr: + server.ip_addr = ip_addr + updated = True + if port and server.port != port: + server.port = port + updated = True + if revision and server.revision != revision: + server.revision = revision + updated = True + if impure_cvars and server.impure_cvars != impure_cvars: + server.impure_cvars = impure_cvars + server.pure_ind = True if impure_cvars == 0 else False + updated = True - if len(servers) > 0: - server = servers[0] - log.debug("Found existing server {0} by name".format(server.server_id)) + return updated - # still haven't found a server by hashkey or name, so we need to create one - if server is None: - server = Server(name=name, hashkey=hashkey) - session.add(server) - session.flush() - log.debug("Created server {0} with hashkey {1}".format( - server.server_id, server.hashkey)) - # detect changed fields - if server.name != name: - server.name = name - session.add(server) +def get_or_create_server(session, name, hashkey, ip_addr, revision, port, impure_cvars): + """ + Find a server by name or create one if not found. Parameters: - if server.hashkey != hashkey: - server.hashkey = hashkey - session.add(server) + session - SQLAlchemy database session factory + name - server name of the server to be found or created + hashkey - server hashkey + ip_addr - the IP address of the server + revision - the xonotic revision number + port - the port number of the server + impure_cvars - the number of impure cvar changes + """ + servers_q = DBSession.query(Server).filter(Server.active_ind) - if server.ip_addr != ip_addr: - server.ip_addr = ip_addr - session.add(server) + if hashkey: + # if the hashkey is provided, we'll use that + servers_q = servers_q.filter((Server.name == name) or (Server.hashkey == hashkey)) + else: + # otherwise, it is just by name + servers_q = servers_q.filter(Server.name == name) - if server.port != port: - server.port = port - session.add(server) + # order by the hashkey, which means any hashkey match will appear first if there are multiple + servers = servers_q.order_by(Server.hashkey, Server.create_dt).all() - if server.revision != revision: - server.revision = revision + if len(servers) == 0: + server = Server(name=name, hashkey=hashkey) session.add(server) + session.flush() + log.debug("Created server {} with hashkey {}.".format(server.server_id, server.hashkey)) + else: + server = servers[0] + if len(servers) == 1: + log.info("Found existing server {}.".format(server.server_id)) - if server.impure_cvars != impure_cvars: - server.impure_cvars = impure_cvars - if impure_cvars > 0: - server.pure_ind = False - else: - server.pure_ind = True + elif len(servers) > 1: + server_id_list = ", ".join(["{}".format(s.server_id) for s in servers]) + log.warn("Multiple servers found ({})! Using the first one ({})." + .format(server_id_list, server.server_id)) + + if update_server(server, name, hashkey, ip_addr, port, revision, impure_cvars): session.add(server) return server -- 2.39.2